Commit 270c57c9 authored by Honfika's avatar Honfika

soks4 cleanup

parent 5bd2c5ce
......@@ -110,7 +110,7 @@ namespace Titanium.Web.Proxy.ProxySocket.Authentication
{
CallBack = callback;
Server.BeginSend(GetAuthenticationBytes(), 0, GetAuthenticationLength(), SocketFlags.None,
new AsyncCallback(this.OnSent), Server);
this.OnSent, Server);
return;
}
......@@ -125,7 +125,7 @@ namespace Titanium.Web.Proxy.ProxySocket.Authentication
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);
Server.BeginReceive(Buffer, 0, 2, SocketFlags.None, this.OnReceive, Server);
}
catch (Exception e)
{
......@@ -152,7 +152,7 @@ namespace Titanium.Web.Proxy.ProxySocket.Authentication
throw new ProxyException("Username/password combination not accepted.");
else
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None,
new AsyncCallback(this.OnReceive), Server);
this.OnReceive, Server);
}
catch (Exception e)
{
......
......@@ -170,11 +170,12 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="remoteEP">An IPEndPoint that represents the remote device.</param>
/// <param name="callback">The method to call when the negotiation is complete.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the HTTPS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public override IAsyncProxyResult BeginNegotiate(IPEndPoint remoteEP, HandShakeComplete callback,
IPEndPoint proxyEndPoint)
IPEndPoint proxyEndPoint, object state)
{
return BeginNegotiate(remoteEP.Address.ToString(), remoteEP.Port, callback, proxyEndPoint);
return BeginNegotiate(remoteEP.Address.ToString(), remoteEP.Port, callback, proxyEndPoint, state);
}
/// <summary>
......@@ -184,14 +185,15 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="port">The port to connect to.</param>
/// <param name="callback">The method to call when the negotiation is complete.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the HTTPS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public override IAsyncProxyResult BeginNegotiate(string host, int port, HandShakeComplete callback,
IPEndPoint proxyEndPoint)
IPEndPoint proxyEndPoint, object state)
{
ProtocolComplete = callback;
Buffer = GetConnectBytes(host, port);
Server.BeginConnect(proxyEndPoint, new AsyncCallback(this.OnConnect), Server);
AsyncResult = new IAsyncProxyResult();
Server.BeginConnect(proxyEndPoint, this.OnConnect, Server);
AsyncResult = new IAsyncProxyResult(state);
return AsyncResult;
}
......@@ -213,7 +215,7 @@ namespace Titanium.Web.Proxy.ProxySocket
try
{
Server.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnConnectSent),
Server.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, this.OnConnectSent,
null);
}
catch (Exception e)
......@@ -233,7 +235,7 @@ namespace Titanium.Web.Proxy.ProxySocket
HandleEndSend(ar, Buffer.Length);
Buffer = new byte[13];
Received = 0;
Server.BeginReceive(Buffer, 0, 13, SocketFlags.None, new AsyncCallback(this.OnConnectReceive), Server);
Server.BeginReceive(Buffer, 0, 13, SocketFlags.None, this.OnConnectReceive, Server);
}
catch (Exception e)
{
......@@ -262,7 +264,7 @@ namespace Titanium.Web.Proxy.ProxySocket
if (Received < 13)
{
Server.BeginReceive(Buffer, Received, 13 - Received, SocketFlags.None,
new AsyncCallback(this.OnConnectReceive), Server);
this.OnConnectReceive, Server);
}
else
{
......@@ -305,7 +307,7 @@ namespace Titanium.Web.Proxy.ProxySocket
}
else
{
Server.BeginReceive(Buffer, 0, 1, SocketFlags.None, new AsyncCallback(this.OnEndHeadersReceive),
Server.BeginReceive(Buffer, 0, 1, SocketFlags.None, this.OnEndHeadersReceive,
Server);
}
}
......
......@@ -31,6 +31,7 @@
using System;
using System.Net;
using System.Net.Sockets;
using System.Security.AccessControl;
// Implements a number of classes to allow Sockets to connect trough a firewall.
namespace Titanium.Web.Proxy.ProxySocket
......@@ -191,34 +192,35 @@ namespace Titanium.Web.Proxy.ProxySocket
{
if (remoteEP == null)
throw new ArgumentNullException();
if (this.ProtocolType != ProtocolType.Tcp || ProxyType == ProxyTypes.None || ProxyEndPoint == null)
if (ProtocolType != ProtocolType.Tcp || ProxyType == ProxyTypes.None || ProxyEndPoint == null)
{
return base.BeginConnect(remoteEP, callback, state);
}
else
CallBack = callback;
if (ProxyType == ProxyTypes.Https)
{
CallBack = callback;
if (ProxyType == ProxyTypes.Https)
{
AsyncResult = (new HttpsHandler(this, ProxyUser, ProxyPass)).BeginNegotiate((IPEndPoint)remoteEP,
new HandShakeComplete(this.OnHandShakeComplete), ProxyEndPoint);
return AsyncResult;
}
else if (ProxyType == ProxyTypes.Socks4)
{
AsyncResult = (new Socks4Handler(this, ProxyUser)).BeginNegotiate((IPEndPoint)remoteEP,
new HandShakeComplete(this.OnHandShakeComplete), ProxyEndPoint);
return AsyncResult;
}
else if (ProxyType == ProxyTypes.Socks5)
{
AsyncResult = (new Socks5Handler(this, ProxyUser, ProxyPass)).BeginNegotiate((IPEndPoint)remoteEP,
new HandShakeComplete(this.OnHandShakeComplete), ProxyEndPoint);
return AsyncResult;
}
AsyncResult = new HttpsHandler(this, ProxyUser, ProxyPass).BeginNegotiate((IPEndPoint)remoteEP,
OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
return null;
if (ProxyType == ProxyTypes.Socks4)
{
AsyncResult = new Socks4Handler(this, ProxyUser).BeginNegotiate((IPEndPoint)remoteEP,
OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
if (ProxyType == ProxyTypes.Socks5)
{
AsyncResult = new Socks5Handler(this, ProxyUser, ProxyPass).BeginNegotiate((IPEndPoint)remoteEP,
OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
return null;
}
/// <summary>
......@@ -243,7 +245,7 @@ namespace Titanium.Web.Proxy.ProxySocket
if (this.ProtocolType != ProtocolType.Tcp || ProxyType == ProxyTypes.None || ProxyEndPoint == null)
{
RemotePort = port;
AsyncResult = BeginDns(host, new HandShakeComplete(this.OnHandShakeComplete));
AsyncResult = BeginDns(host, this.OnHandShakeComplete, state);
return AsyncResult;
}
else
......@@ -251,19 +253,21 @@ namespace Titanium.Web.Proxy.ProxySocket
if (ProxyType == ProxyTypes.Https)
{
AsyncResult = (new HttpsHandler(this, ProxyUser, ProxyPass)).BeginNegotiate(host, port,
new HandShakeComplete(this.OnHandShakeComplete), ProxyEndPoint);
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
else if (ProxyType == ProxyTypes.Socks4)
if (ProxyType == ProxyTypes.Socks4)
{
AsyncResult = (new Socks4Handler(this, ProxyUser)).BeginNegotiate(host, port,
new HandShakeComplete(this.OnHandShakeComplete), ProxyEndPoint);
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
else if (ProxyType == ProxyTypes.Socks5)
if (ProxyType == ProxyTypes.Socks5)
{
AsyncResult = (new Socks5Handler(this, ProxyUser, ProxyPass)).BeginNegotiate(host, port,
new HandShakeComplete(this.OnHandShakeComplete), ProxyEndPoint);
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
......@@ -304,14 +308,15 @@ namespace Titanium.Web.Proxy.ProxySocket
/// </summary>
/// <param name="host">The host to resolve.</param>
/// <param name="callback">The method to call when the hostname has been resolved.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncResult instance that references the asynchronous request.</returns>
/// <exception cref="SocketException">There was an error while trying to resolve the host.</exception>
internal IAsyncProxyResult BeginDns(string host, HandShakeComplete callback)
internal IAsyncProxyResult BeginDns(string host, HandShakeComplete callback, object state)
{
try
{
Dns.BeginGetHostEntry(host, new AsyncCallback(this.OnResolved), this);
return new IAsyncProxyResult();
Dns.BeginGetHostEntry(host, this.OnResolved, this);
return new IAsyncProxyResult(state);
}
catch
{
......@@ -328,7 +333,7 @@ namespace Titanium.Web.Proxy.ProxySocket
try
{
IPHostEntry dns = Dns.EndGetHostEntry(asyncResult);
base.BeginConnect(new IPEndPoint(dns.AddressList[0], RemotePort), new AsyncCallback(this.OnConnect),
base.BeginConnect(new IPEndPoint(dns.AddressList[0], RemotePort), this.OnConnect,
State);
}
catch (Exception e)
......@@ -358,47 +363,27 @@ namespace Titanium.Web.Proxy.ProxySocket
/// Called when the Socket has finished talking to the proxy server and is ready to relay data.
/// </summary>
/// <param name="error">The error to throw when the EndConnect method is called.</param>
private void OnHandShakeComplete(Exception error)
private void OnHandShakeComplete(Exception? error)
{
if (error != null)
this.Close();
ToThrow = error;
CallBack?.Invoke(AsyncResult);
AsyncResult.Reset();
if (CallBack != null)
CallBack(AsyncResult);
}
/// <summary>
/// Gets or sets the EndPoint of the proxy server.
/// </summary>
/// <value>An IPEndPoint object that holds the IP address and the port of the proxy server.</value>
public IPEndPoint ProxyEndPoint
{
get
{
return _proxyEndPoint;
}
set
{
_proxyEndPoint = value;
}
}
public IPEndPoint ProxyEndPoint { get; set; }
/// <summary>
/// Gets or sets the type of proxy server to use.
/// </summary>
/// <value>One of the ProxyTypes values.</value>
public ProxyTypes ProxyType
{
get
{
return _proxyType;
}
set
{
_proxyType = value;
}
}
public ProxyTypes ProxyType { get; set; } = ProxyTypes.None;
/// <summary>
/// Gets or sets a user-defined object.
......@@ -421,16 +406,10 @@ namespace Titanium.Web.Proxy.ProxySocket
/// </summary>
/// <value>A string that holds the username that's used when authenticating with the proxy.</value>
/// <exception cref="ArgumentNullException">The specified value is null.</exception>
public string? ProxyUser
public string ProxyUser
{
get
{
return _proxyUser;
}
set
{
_proxyUser = value ?? throw new ArgumentNullException();
}
get => _proxyUser;
set => _proxyUser = value ?? throw new ArgumentNullException();
}
/// <summary>
......@@ -438,92 +417,41 @@ namespace Titanium.Web.Proxy.ProxySocket
/// </summary>
/// <value>A string that holds the password that's used when authenticating with the proxy.</value>
/// <exception cref="ArgumentNullException">The specified value is null.</exception>
public string? ProxyPass
public string ProxyPass
{
get
{
return _proxyPass;
}
set
{
_proxyPass = value ?? throw new ArgumentNullException();
}
get => _proxyPass;
set => _proxyPass = value ?? throw new ArgumentNullException();
}
/// <summary>
/// Gets or sets the asynchronous result object.
/// </summary>
/// <value>An instance of the IAsyncProxyResult class.</value>
private IAsyncProxyResult AsyncResult
{
get
{
return _asyncResult;
}
set
{
_asyncResult = value;
}
}
private IAsyncProxyResult AsyncResult { get; set; }
/// <summary>
/// Gets or sets the exception to throw when the EndConnect method is called.
/// </summary>
/// <value>An instance of the Exception class (or subclasses of Exception).</value>
private Exception ToThrow
{
get
{
return _toThrow;
}
set
{
_toThrow = value;
}
}
private Exception? ToThrow { get; set; }
/// <summary>
/// Gets or sets the remote port the user wants to connect to.
/// </summary>
/// <value>An integer that specifies the port the user wants to connect to.</value>
private int RemotePort
{
get
{
return _remotePort;
}
set
{
_remotePort = value;
}
}
private int RemotePort { get; set; }
// private variables
/// <summary>Holds the value of the State property.</summary>
private object _state;
/// <summary>Holds the value of the ProxyEndPoint property.</summary>
private IPEndPoint _proxyEndPoint;
/// <summary>Holds the value of the ProxyType property.</summary>
private ProxyTypes _proxyType = ProxyTypes.None;
/// <summary>Holds the value of the ProxyUser property.</summary>
private string? _proxyUser;
private string _proxyUser = string.Empty;
/// <summary>Holds the value of the ProxyPass property.</summary>
private string? _proxyPass;
private string _proxyPass = string.Empty;
/// <summary>Holds a pointer to the method that should be called when the Socket is connected to the remote device.</summary>
private AsyncCallback CallBack;
/// <summary>Holds the value of the AsyncResult property.</summary>
private IAsyncProxyResult _asyncResult;
/// <summary>Holds the value of the ToThrow property.</summary>
private Exception _toThrow;
/// <summary>Holds the value of the RemotePort property.</summary>
private int _remotePort;
}
}
......@@ -29,6 +29,7 @@
*/
using System;
using System.Buffers;
using System.Net;
using System.Net.Sockets;
using System.Text;
......@@ -53,47 +54,61 @@ namespace Titanium.Web.Proxy.ProxySocket
/// </summary>
/// <param name="host">The host to connect to.</param>
/// <param name="port">The port to connect to.</param>
/// <param name="buffer">The buffer which contains the result data.</param>
/// <returns>An array of bytes that has to be sent when the user wants to connect to a specific host/port combination.</returns>
/// <remarks>Resolving the host name will be done at server side. Do note that some SOCKS4 servers do not implement this functionality.</remarks>
/// <exception cref="ArgumentNullException"><c>host</c> is null.</exception>
/// <exception cref="ArgumentException"><c>port</c> is invalid.</exception>
private byte[] GetHostPortBytes(string host, int port)
private int GetHostPortBytes(string host, int port, Memory<byte> buffer)
{
if (host == null)
throw new ArgumentNullException();
throw new ArgumentNullException(nameof(host));
if (port <= 0 || port > 65535)
throw new ArgumentException();
byte[] connect = new byte[10 + Username.Length + host.Length];
throw new ArgumentException(nameof(port));
int length = 10 + Username.Length + host.Length;
if (buffer.Length < length)
throw new ArgumentException(nameof(buffer));
var connect = buffer.Span;
connect[0] = 4;
connect[1] = 1;
Array.Copy(PortToBytes(port), 0, connect, 2, 2);
PortToBytes(port, connect.Slice(2));
connect[4] = connect[5] = connect[6] = 0;
connect[7] = 1;
Array.Copy(Encoding.ASCII.GetBytes(Username), 0, connect, 8, Username.Length);
var userNameArray = Encoding.ASCII.GetBytes(Username);
userNameArray.CopyTo(connect.Slice(8));
connect[8 + Username.Length] = 0;
Array.Copy(Encoding.ASCII.GetBytes(host), 0, connect, 9 + Username.Length, host.Length);
Encoding.ASCII.GetBytes(host).CopyTo(connect.Slice(9 + userNameArray.Length));
connect[9 + Username.Length + host.Length] = 0;
return connect;
return length;
}
/// <summary>
/// Creates an array of bytes that has to be sent when the user wants to connect to a specific IPEndPoint.
/// </summary>
/// <param name="remoteEP">The IPEndPoint to connect to.</param>
/// <param name="buffer">The buffer which contains the result data.</param>
/// <returns>An array of bytes that has to be sent when the user wants to connect to a specific IPEndPoint.</returns>
/// <exception cref="ArgumentNullException"><c>remoteEP</c> is null.</exception>
private byte[] GetEndPointBytes(IPEndPoint remoteEP)
private int GetEndPointBytes(IPEndPoint remoteEP, Memory<byte> buffer)
{
if (remoteEP == null)
throw new ArgumentNullException();
byte[] connect = new byte[9 + Username.Length];
throw new ArgumentNullException(nameof(remoteEP));
int length = 9 + Username.Length;
if (buffer.Length < length)
throw new ArgumentException(nameof(buffer));
var connect = buffer.Span;
connect[0] = 4;
connect[1] = 1;
Array.Copy(PortToBytes(remoteEP.Port), 0, connect, 2, 2);
Array.Copy(remoteEP.Address.GetAddressBytes(), 0, connect, 4, 4);
Array.Copy(Encoding.ASCII.GetBytes(Username), 0, connect, 8, Username.Length);
PortToBytes(remoteEP.Port, connect.Slice(2));
remoteEP.Address.GetAddressBytes().CopyTo(connect.Slice(4));
Encoding.ASCII.GetBytes(Username).CopyTo(connect.Slice(8));
connect[8 + Username.Length] = 0;
return connect;
return length;
}
/// <summary>
......@@ -108,7 +123,16 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
public override void Negotiate(string host, int port)
{
Negotiate(GetHostPortBytes(host, port));
var buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
int length = GetHostPortBytes(host, port, buffer);
Negotiate(buffer, length);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
/// <summary>
......@@ -121,26 +145,36 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
public override void Negotiate(IPEndPoint remoteEP)
{
Negotiate(GetEndPointBytes(remoteEP));
var buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
int length = GetEndPointBytes(remoteEP, buffer);
Negotiate(buffer, length);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
/// <summary>
/// Starts negotiating with the SOCKS server.
/// </summary>
/// <param name="connect">The bytes to send when trying to authenticate.</param>
/// <param name="length">The byte count to send when trying to authenticate.</param>
/// <exception cref="ArgumentNullException"><c>connect</c> is null.</exception>
/// <exception cref="ArgumentException"><c>connect</c> is too small.</exception>
/// <exception cref="ProxyException">The proxy rejected the request.</exception>
/// <exception cref="SocketException">An operating system error occurs while accessing the Socket.</exception>
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
private void Negotiate(byte[] connect)
private void Negotiate(byte[] connect, int length)
{
if (connect == null)
throw new ArgumentNullException();
if (connect.Length < 2)
throw new ArgumentException();
if (Server.Send(connect) < connect.Length)
if (Server.Send(connect, 0, length, SocketFlags.None) < connect.Length)
throw new SocketException(10054);
byte[] buffer = ReadBytes(8);
if (buffer[1] != 90)
{
......@@ -156,14 +190,16 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="port">The remote port to connect to.</param>
/// <param name="callback">The method to call when the connection has been established.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the SOCKS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public override IAsyncProxyResult BeginNegotiate(string host, int port, HandShakeComplete callback,
IPEndPoint proxyEndPoint)
IPEndPoint proxyEndPoint, object state)
{
ProtocolComplete = callback;
Buffer = GetHostPortBytes(host, port);
Server.BeginConnect(proxyEndPoint, new AsyncCallback(this.OnConnect), Server);
AsyncResult = new IAsyncProxyResult();
Buffer = ArrayPool<byte>.Shared.Rent(1024);
BufferCount = GetHostPortBytes(host, port, Buffer);
Server.BeginConnect(proxyEndPoint, OnConnect, Server);
AsyncResult = new IAsyncProxyResult(state);
return AsyncResult;
}
......@@ -173,14 +209,16 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="remoteEP">An IPEndPoint that represents the remote device.</param>
/// <param name="callback">The method to call when the connection has been established.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the SOCKS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public override IAsyncProxyResult BeginNegotiate(IPEndPoint remoteEP, HandShakeComplete callback,
IPEndPoint proxyEndPoint)
IPEndPoint proxyEndPoint, object state)
{
ProtocolComplete = callback;
Buffer = GetEndPointBytes(remoteEP);
Server.BeginConnect(proxyEndPoint, new AsyncCallback(this.OnConnect), Server);
AsyncResult = new IAsyncProxyResult();
Buffer = ArrayPool<byte>.Shared.Rent(1024);
BufferCount = GetEndPointBytes(remoteEP, Buffer);
Server.BeginConnect(proxyEndPoint, OnConnect, Server);
AsyncResult = new IAsyncProxyResult(state);
return AsyncResult;
}
......@@ -196,17 +234,17 @@ namespace Titanium.Web.Proxy.ProxySocket
}
catch (Exception e)
{
ProtocolComplete(e);
OnProtocolComplete(e);
return;
}
try
{
Server.BeginSend(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnSent), Server);
Server.BeginSend(Buffer, 0, BufferCount, SocketFlags.None, OnSent, Server);
}
catch (Exception e)
{
ProtocolComplete(e);
OnProtocolComplete(e);
}
}
......@@ -218,24 +256,22 @@ namespace Titanium.Web.Proxy.ProxySocket
{
try
{
HandleEndSend(ar, Buffer.Length);
HandleEndSend(ar, BufferCount);
}
catch (Exception e)
{
ProtocolComplete(e);
OnProtocolComplete(e);
return;
}
try
{
Buffer = new byte[8];
Received = 0;
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReceive),
Server);
Server.BeginReceive(Buffer, 0, 8, SocketFlags.None, OnReceive, Server);
}
catch (Exception e)
{
ProtocolComplete(e);
OnProtocolComplete(e);
}
}
......@@ -251,23 +287,29 @@ namespace Titanium.Web.Proxy.ProxySocket
if (Received == 8)
{
if (Buffer[1] == 90)
ProtocolComplete(null);
OnProtocolComplete(null);
else
{
Server.Close();
ProtocolComplete(new ProxyException("Negotiation failed."));
OnProtocolComplete(new ProxyException("Negotiation failed."));
}
}
else
{
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None,
new AsyncCallback(this.OnReceive), Server);
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None, OnReceive,
Server);
}
}
catch (Exception e)
{
ProtocolComplete(e);
OnProtocolComplete(e);
}
}
private void OnProtocolComplete(Exception? exception)
{
ArrayPool<byte>.Shared.Return(Buffer);
ProtocolComplete(exception);
}
}
}
......@@ -220,14 +220,15 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="port">The port to connect to.</param>
/// <param name="callback">The method to call when the negotiation is complete.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the SOCKS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public override IAsyncProxyResult BeginNegotiate(string host, int port, HandShakeComplete callback,
IPEndPoint proxyEndPoint)
IPEndPoint proxyEndPoint, object state)
{
ProtocolComplete = callback;
HandShake = GetHostPortBytes(host, port);
Server.BeginConnect(proxyEndPoint, new AsyncCallback(this.OnConnect), Server);
AsyncResult = new IAsyncProxyResult();
Server.BeginConnect(proxyEndPoint, this.OnConnect, Server);
AsyncResult = new IAsyncProxyResult(state);
return AsyncResult;
}
......@@ -237,14 +238,15 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="remoteEP">An IPEndPoint that represents the remote device.</param>
/// <param name="callback">The method to call when the negotiation is complete.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the SOCKS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public override IAsyncProxyResult BeginNegotiate(IPEndPoint remoteEP, HandShakeComplete callback,
IPEndPoint proxyEndPoint)
IPEndPoint proxyEndPoint, object state)
{
ProtocolComplete = callback;
HandShake = GetEndPointBytes(remoteEP);
Server.BeginConnect(proxyEndPoint, new AsyncCallback(this.OnConnect), Server);
AsyncResult = new IAsyncProxyResult();
Server.BeginConnect(proxyEndPoint, this.OnConnect, Server);
AsyncResult = new IAsyncProxyResult(state);
return AsyncResult;
}
......@@ -266,7 +268,7 @@ namespace Titanium.Web.Proxy.ProxySocket
try
{
Server.BeginSend(new byte[] { 5, 2, 0, 2 }, 0, 4, SocketFlags.None, new AsyncCallback(this.OnAuthSent),
Server.BeginSend(new byte[] { 5, 2, 0, 2 }, 0, 4, SocketFlags.None, this.OnAuthSent,
Server);
}
catch (Exception e)
......@@ -295,7 +297,7 @@ namespace Titanium.Web.Proxy.ProxySocket
{
Buffer = new byte[1024];
Received = 0;
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnAuthReceive),
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, this.OnAuthReceive,
Server);
}
catch (Exception e)
......@@ -325,7 +327,7 @@ namespace Titanium.Web.Proxy.ProxySocket
if (Received < 2)
{
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None,
new AsyncCallback(this.OnAuthReceive), Server);
this.OnAuthReceive, Server);
}
else
{
......@@ -343,7 +345,7 @@ namespace Titanium.Web.Proxy.ProxySocket
return;
}
authenticate.BeginAuthenticate(new HandShakeComplete(this.OnAuthenticated));
authenticate.BeginAuthenticate(this.OnAuthenticated);
}
}
catch (Exception e)
......@@ -366,7 +368,7 @@ namespace Titanium.Web.Proxy.ProxySocket
try
{
Server.BeginSend(HandShake, 0, HandShake.Length, SocketFlags.None, new AsyncCallback(this.OnSent),
Server.BeginSend(HandShake, 0, HandShake.Length, SocketFlags.None, this.OnSent,
Server);
}
catch (Exception ex)
......@@ -395,7 +397,7 @@ namespace Titanium.Web.Proxy.ProxySocket
{
Buffer = new byte[5];
Received = 0;
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReceive),
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, this.OnReceive,
Server);
}
catch (Exception e)
......@@ -426,7 +428,7 @@ namespace Titanium.Web.Proxy.ProxySocket
ProcessReply(Buffer);
else
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None,
new AsyncCallback(this.OnReceive), Server);
this.OnReceive, Server);
}
catch (Exception e)
{
......@@ -457,7 +459,7 @@ namespace Titanium.Web.Proxy.ProxySocket
}
Received = 0;
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, new AsyncCallback(this.OnReadLast), Server);
Server.BeginReceive(Buffer, 0, Buffer.Length, SocketFlags.None, this.OnReadLast, Server);
}
/// <summary>
......@@ -482,7 +484,7 @@ namespace Titanium.Web.Proxy.ProxySocket
ProtocolComplete(null);
else
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None,
new AsyncCallback(this.OnReadLast), Server);
this.OnReadLast, Server);
}
catch (Exception e)
{
......
......@@ -37,7 +37,7 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <summary>
/// References the callback method to be called when the protocol negotiation is completed.
/// </summary>
internal delegate void HandShakeComplete(Exception error);
internal delegate void HandShakeComplete(Exception? error);
/// <summary>
/// Implements a specific version of the SOCKS protocol. This is an abstract class; it must be inherited.
......@@ -56,6 +56,18 @@ namespace Titanium.Web.Proxy.ProxySocket
Username = user;
}
/// <summary>
/// Converts a port number to an array of bytes.
/// </summary>
/// <param name="port">The port to convert.</param>
/// <param name="buffer">The buffer which contains the result data.</param>
/// <returns>An array of two bytes that represents the specified port.</returns>
protected void PortToBytes(int port, Span<byte> buffer)
{
buffer[0] = (byte)(port / 256);
buffer[1] = (byte)(port % 256);
}
/// <summary>
/// Converts a port number to an array of bytes.
/// </summary>
......@@ -163,11 +175,7 @@ namespace Titanium.Web.Proxy.ProxySocket
/// Gets or sets the return value of the BeginConnect call.
/// </summary>
/// <value>An IAsyncProxyResult object that is the return value of the BeginConnect call.</value>
protected IAsyncProxyResult AsyncResult
{
get => _asyncResult;
set => _asyncResult = value;
}
protected IAsyncProxyResult AsyncResult { get; set; }
/// <summary>
/// Gets or sets a byte buffer.
......@@ -175,6 +183,11 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <value>An array of bytes.</value>
protected byte[] Buffer { get; set; }
/// <summary>
/// Gets or sets actual data count in the buffer.
/// </summary>
protected int BufferCount { get; set; }
/// <summary>
/// Gets or sets the number of bytes that have been received from the remote proxy server.
/// </summary>
......@@ -188,9 +201,6 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <summary>Holds the value of the Username property.</summary>
private string _username;
/// <summary>Holds the value of the AsyncResult property.</summary>
private IAsyncProxyResult _asyncResult;
/// <summary>Holds the address of the method to call when the SOCKS protocol has been completed.</summary>
protected HandShakeComplete ProtocolComplete;
......@@ -213,9 +223,10 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="remoteEP">An IPEndPoint that represents the remote device. </param>
/// <param name="callback">The method to call when the connection has been established.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the SOCKS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public abstract IAsyncProxyResult BeginNegotiate(IPEndPoint remoteEP, HandShakeComplete callback,
IPEndPoint proxyEndPoint);
IPEndPoint proxyEndPoint, object state);
/// <summary>
/// Starts negotiating asynchronously with a SOCKS proxy server.
......@@ -224,8 +235,9 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="port">The remote port to connect to.</param>
/// <param name="callback">The method to call when the connection has been established.</param>
/// <param name="proxyEndPoint">The IPEndPoint of the SOCKS proxy server.</param>
/// <param name="state">The state.</param>
/// <returns>An IAsyncProxyResult that references the asynchronous connection.</returns>
public abstract IAsyncProxyResult BeginNegotiate(string host, int port, HandShakeComplete callback,
IPEndPoint proxyEndPoint);
IPEndPoint proxyEndPoint, object state);
}
}
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