Commit 8323f79f authored by Honfika's avatar Honfika

socks5 refactored + small fies

parent 270c57c9
...@@ -395,40 +395,41 @@ retry: ...@@ -395,40 +395,41 @@ retry:
tcpServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); tcpServerSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
} }
var connectTask = socks ((ProxySocket.ProxySocket)tcpServerSocket).Connect(ipAddress, port);
? ProxySocketConnectionTaskFactory.CreateTask((ProxySocket.ProxySocket)tcpServerSocket, ipAddress, port) // var connectTask = socks
: SocketConnectionTaskFactory.CreateTask(tcpServerSocket, ipAddress, port); // ? ProxySocketConnectionTaskFactory.CreateTask((ProxySocket.ProxySocket)tcpServerSocket, ipAddress, port)
// : SocketConnectionTaskFactory.CreateTask(tcpServerSocket, ipAddress, port);
await Task.WhenAny(connectTask, Task.Delay(proxyServer.ConnectTimeOutSeconds * 1000, cancellationToken));
if (!connectTask.IsCompleted || !tcpServerSocket.Connected) // await Task.WhenAny(connectTask, Task.Delay(proxyServer.ConnectTimeOutSeconds * 1000, cancellationToken));
{ // if (!connectTask.IsCompleted || !tcpServerSocket.Connected)
// here we can just do some cleanup and let the loop continue since // {
// we will either get a connection or wind up with a null tcpClient // // here we can just do some cleanup and let the loop continue since
// which will throw // // we will either get a connection or wind up with a null tcpClient
try // // which will throw
{ // try
connectTask.Dispose(); // {
} // connectTask.Dispose();
catch // }
{ // catch
// ignore // {
} // // ignore
try // }
{ // try
#if NET45 // {
tcpServerSocket?.Close(); //#if NET45
#else // tcpServerSocket?.Close();
tcpServerSocket?.Dispose(); //#else
#endif // tcpServerSocket?.Dispose();
tcpServerSocket = null; //#endif
} // tcpServerSocket = null;
catch // }
{ // catch
// ignore // {
} // // ignore
// }
continue;
} // continue;
// }
break; break;
} }
......
...@@ -90,45 +90,20 @@ namespace Titanium.Web.Proxy.ProxySocket.Authentication ...@@ -90,45 +90,20 @@ namespace Titanium.Web.Proxy.ProxySocket.Authentication
/// Gets or sets a byt array that can be used to store data. /// Gets or sets a byt array that can be used to store data.
/// </summary> /// </summary>
/// <value>A byte array to store data.</value> /// <value>A byte array to store data.</value>
protected byte[] Buffer protected byte[] Buffer { get; set; }
{
get
{
return _buffer;
}
set
{
_buffer = value;
}
}
/// <summary> /// <summary>
/// Gets or sets the number of bytes that have been received from the remote proxy server. /// Gets or sets the number of bytes that have been received from the remote proxy server.
/// </summary> /// </summary>
/// <value>An integer that holds the number of bytes that have been received from the remote proxy server.</value> /// <value>An integer that holds the number of bytes that have been received from the remote proxy server.</value>
protected int Received protected int Received { get; set; }
{
get
{
return _received;
}
set
{
_received = value;
}
}
// private variables // private variables
/// <summary>Holds the value of the Buffer property.</summary>
private byte[] _buffer;
/// <summary>Holds the value of the Server property.</summary> /// <summary>Holds the value of the Server property.</summary>
private Socket _server; private Socket _server;
/// <summary>Holds the address of the method to call when the proxy has authenticated the client.</summary> /// <summary>Holds the address of the method to call when the proxy has authenticated the client.</summary>
protected HandShakeComplete CallBack; protected HandShakeComplete CallBack;
/// <summary>Holds the value of the Received property.</summary>
private int _received;
} }
} }
...@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -73,7 +73,7 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <returns>An array of bytes that has to be sent when the user wants to connect to a specific IPEndPoint.</returns> /// <returns>An array of bytes that has to be sent when the user wants to connect to a specific IPEndPoint.</returns>
private byte[] GetConnectBytes(string host, int port) private byte[] GetConnectBytes(string host, int port)
{ {
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine(string.Format("CONNECT {0}:{1} HTTP/1.1", host, port)); sb.AppendLine(string.Format("CONNECT {0}:{1} HTTP/1.1", host, port));
sb.AppendLine(string.Format("Host: {0}:{1}", host, port)); sb.AppendLine(string.Format("Host: {0}:{1}", host, port));
if (!string.IsNullOrEmpty(Username)) if (!string.IsNullOrEmpty(Username))
...@@ -92,12 +92,14 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -92,12 +92,14 @@ namespace Titanium.Web.Proxy.ProxySocket
/// Verifies that proxy server successfully connected to requested host /// Verifies that proxy server successfully connected to requested host
/// </summary> /// </summary>
/// <param name="buffer">Input data array</param> /// <param name="buffer">Input data array</param>
private void VerifyConnectHeader(byte[] buffer) /// <param name="length">The data count in the buffer</param>
private void VerifyConnectHeader(byte[] buffer, int length)
{ {
string header = Encoding.ASCII.GetString(buffer); string header = Encoding.ASCII.GetString(buffer, 0, length);
if ((!header.StartsWith("HTTP/1.1 ", StringComparison.OrdinalIgnoreCase) && if ((!header.StartsWith("HTTP/1.1 ", StringComparison.OrdinalIgnoreCase) &&
!header.StartsWith("HTTP/1.0 ", StringComparison.OrdinalIgnoreCase)) || !header.EndsWith(" ")) !header.StartsWith("HTTP/1.0 ", StringComparison.OrdinalIgnoreCase)) || !header.EndsWith(" "))
throw new ProtocolViolationException(); throw new ProtocolViolationException();
string code = header.Substring(9, 3); string code = header.Substring(9, 3);
if (code != "200") if (code != "200")
throw new ProxyException("Invalid HTTP status. Code: " + code); throw new ProxyException("Invalid HTTP status. Code: " + code);
...@@ -134,20 +136,21 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -134,20 +136,21 @@ namespace Titanium.Web.Proxy.ProxySocket
{ {
if (host == null) if (host == null)
throw new ArgumentNullException(); throw new ArgumentNullException();
if (port <= 0 || port > 65535 || host.Length > 255) if (port <= 0 || port > 65535 || host.Length > 255)
throw new ArgumentException(); throw new ArgumentException();
byte[] buffer = GetConnectBytes(host, port); byte[] buffer = GetConnectBytes(host, port);
if (Server.Send(buffer, 0, buffer.Length, SocketFlags.None) < buffer.Length) if (Server.Send(buffer, 0, buffer.Length, SocketFlags.None) < buffer.Length)
{ {
throw new SocketException(10054); throw new SocketException(10054);
} }
buffer = ReadBytes(13); ReadBytes(buffer, 13); // buffer is always longer than 13 bytes. Check the code in GetConnectBytes
VerifyConnectHeader(buffer); VerifyConnectHeader(buffer, 13);
// Read bytes 1 by 1 until we reach "\r\n\r\n" // Read bytes 1 by 1 until we reach "\r\n\r\n"
int receivedNewlineChars = 0; int receivedNewlineChars = 0;
buffer = new byte[1];
while (receivedNewlineChars < 4) while (receivedNewlineChars < 4)
{ {
int recv = Server.Receive(buffer, 0, 1, SocketFlags.None); int recv = Server.Receive(buffer, 0, 1, SocketFlags.None);
...@@ -209,7 +212,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -209,7 +212,7 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
catch (Exception e) catch (Exception e)
{ {
ProtocolComplete(e); OnProtocolComplete(e);
return; return;
} }
...@@ -220,7 +223,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -220,7 +223,7 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
catch (Exception e) catch (Exception e)
{ {
ProtocolComplete(e); OnProtocolComplete(e);
} }
} }
...@@ -239,7 +242,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -239,7 +242,7 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
catch (Exception e) catch (Exception e)
{ {
ProtocolComplete(e); OnProtocolComplete(e);
} }
} }
...@@ -255,7 +258,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -255,7 +258,7 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
catch (Exception e) catch (Exception e)
{ {
ProtocolComplete(e); OnProtocolComplete(e);
return; return;
} }
...@@ -268,13 +271,13 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -268,13 +271,13 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
else else
{ {
VerifyConnectHeader(Buffer); VerifyConnectHeader(Buffer, 13);
ReadUntilHeadersEnd(true); ReadUntilHeadersEnd(true);
} }
} }
catch (Exception e) catch (Exception e)
{ {
ProtocolComplete(e); OnProtocolComplete(e);
} }
} }
...@@ -303,7 +306,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -303,7 +306,7 @@ namespace Titanium.Web.Proxy.ProxySocket
if (_receivedNewlineChars == 4) if (_receivedNewlineChars == 4)
{ {
ProtocolComplete(null); OnProtocolComplete(null);
} }
else else
{ {
...@@ -327,10 +330,16 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -327,10 +330,16 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
catch (Exception e) catch (Exception e)
{ {
ProtocolComplete(e); OnProtocolComplete(e);
} }
} }
protected override void OnProtocolComplete(Exception? exception)
{
// do not return the base Buffer
ProtocolComplete(exception);
}
/// <summary> /// <summary>
/// Gets or sets the password to use when authenticating with the HTTPS server. /// Gets or sets the password to use when authenticating with the HTTPS server.
/// </summary> /// </summary>
......
...@@ -42,73 +42,40 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -42,73 +42,40 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <param name="stateObject">An object that contains state information for this request.</param> /// <param name="stateObject">An object that contains state information for this request.</param>
internal IAsyncProxyResult(object stateObject = null) internal IAsyncProxyResult(object stateObject = null)
{ {
_stateObject = stateObject; AsyncState = stateObject;
_completed = false; IsCompleted = false;
if (_waitHandle != null) _waitHandle?.Reset();
_waitHandle.Reset();
} }
/// <summary>Initializes the internal variables of this object</summary> /// <summary>Initializes the internal variables of this object</summary>
internal void Reset() internal void Reset()
{ {
_stateObject = null; //AsyncState = null;
_completed = true; IsCompleted = true;
if (_waitHandle != null) _waitHandle?.Set();
_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> /// <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> /// <value>A boolean that indicates whether the server has completed processing the call.</value>
public bool IsCompleted public bool IsCompleted { get; private set; }
{
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> /// <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> /// <value>Returns false.</value>
public bool CompletedSynchronously public bool CompletedSynchronously => false;
{
get
{
return false;
}
}
/// <summary>Gets an object that was passed as the state parameter of the BeginXXXX method call.</summary> /// <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> /// <value>The object that was passed as the state parameter of the BeginXXXX method call.</value>
public object AsyncState public object AsyncState { get; private set; }
{
get
{
return _stateObject;
}
}
/// <summary> /// <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. /// 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. /// 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> ///</summary>
/// <value>The WaitHandle associated with this asynchronous result.</value> /// <value>The WaitHandle associated with this asynchronous result.</value>
public WaitHandle AsyncWaitHandle public WaitHandle AsyncWaitHandle => _waitHandle ??= new ManualResetEvent(false);
{
get
{
if (_waitHandle == null)
_waitHandle = new ManualResetEvent(false);
return _waitHandle;
}
}
// private variables // 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> /// <summary>Holds the value of the WaitHandle property.</summary>
private ManualResetEvent _waitHandle; private ManualResetEvent _waitHandle;
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
using System; using System;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Security.AccessControl;
// Implements a number of classes to allow Sockets to connect trough a firewall. // Implements a number of classes to allow Sockets to connect trough a firewall.
namespace Titanium.Web.Proxy.ProxySocket namespace Titanium.Web.Proxy.ProxySocket
...@@ -104,6 +103,21 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -104,6 +103,21 @@ namespace Titanium.Web.Proxy.ProxySocket
ToThrow = new InvalidOperationException(); ToThrow = new InvalidOperationException();
} }
/// <summary>
/// Establishes a connection to a remote device.
/// </summary>
/// <param name="address">An EndPoint address that represents the remote device.</param>
/// <param name="port">An EndPoint port that represents the remote device.</param>
/// <exception cref="ArgumentNullException">The remoteEP parameter is a null reference (Nothing in Visual Basic).</exception>
/// <exception cref="SocketException">An operating system error occurs while accessing the Socket.</exception>
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
/// <exception cref="ProxyException">An error occurred while talking to the proxy server.</exception>
public new void Connect(IPAddress address, int port)
{
var remoteEP = new IPEndPoint(address, port);
Connect(remoteEP);
}
/// <summary> /// <summary>
/// Establishes a connection to a remote device. /// Establishes a connection to a remote device.
/// </summary> /// </summary>
...@@ -144,20 +158,22 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -144,20 +158,22 @@ namespace Titanium.Web.Proxy.ProxySocket
public new void Connect(string host, int port) public new void Connect(string host, int port)
{ {
if (host == null) if (host == null)
throw new ArgumentNullException("<host> cannot be null."); throw new ArgumentNullException(nameof(host));
if (port <= 0 || port > 65535) if (port <= 0 || port > 65535)
throw new ArgumentException("Invalid port."); throw new ArgumentException(nameof(port));
if (this.ProtocolType != ProtocolType.Tcp || ProxyType == ProxyTypes.None || ProxyEndPoint == null) if (this.ProtocolType != ProtocolType.Tcp || ProxyType == ProxyTypes.None || ProxyEndPoint == null)
base.Connect(new IPEndPoint(Dns.GetHostEntry(host).AddressList[0], port)); base.Connect(new IPEndPoint(Dns.GetHostEntry(host).AddressList[0], port));
else else
{ {
base.Connect(ProxyEndPoint); base.Connect(ProxyEndPoint);
if (ProxyType == ProxyTypes.Https) if (ProxyType == ProxyTypes.Https)
(new HttpsHandler(this, ProxyUser, ProxyPass)).Negotiate(host, port); new HttpsHandler(this, ProxyUser, ProxyPass).Negotiate(host, port);
else if (ProxyType == ProxyTypes.Socks4) else if (ProxyType == ProxyTypes.Socks4)
(new Socks4Handler(this, ProxyUser)).Negotiate(host, port); new Socks4Handler(this, ProxyUser).Negotiate(host, port);
else if (ProxyType == ProxyTypes.Socks5) else if (ProxyType == ProxyTypes.Socks5)
(new Socks5Handler(this, ProxyUser, ProxyPass)).Negotiate(host, port); new Socks5Handler(this, ProxyUser, ProxyPass).Negotiate(host, port);
} }
} }
...@@ -248,31 +264,29 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -248,31 +264,29 @@ namespace Titanium.Web.Proxy.ProxySocket
AsyncResult = BeginDns(host, this.OnHandShakeComplete, state); AsyncResult = BeginDns(host, this.OnHandShakeComplete, state);
return AsyncResult; return AsyncResult;
} }
else
if (ProxyType == ProxyTypes.Https)
{ {
if (ProxyType == ProxyTypes.Https) AsyncResult = (new HttpsHandler(this, ProxyUser, ProxyPass)).BeginNegotiate(host, port,
{ this.OnHandShakeComplete, ProxyEndPoint, state);
AsyncResult = (new HttpsHandler(this, ProxyUser, ProxyPass)).BeginNegotiate(host, port, return AsyncResult;
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
if (ProxyType == ProxyTypes.Socks4)
{
AsyncResult = (new Socks4Handler(this, ProxyUser)).BeginNegotiate(host, port,
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
if (ProxyType == ProxyTypes.Socks5)
{
AsyncResult = (new Socks5Handler(this, ProxyUser, ProxyPass)).BeginNegotiate(host, port,
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
return null;
} }
if (ProxyType == ProxyTypes.Socks4)
{
AsyncResult = (new Socks4Handler(this, ProxyUser)).BeginNegotiate(host, port,
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
if (ProxyType == ProxyTypes.Socks5)
{
AsyncResult = (new Socks5Handler(this, ProxyUser, ProxyPass)).BeginNegotiate(host, port,
this.OnHandShakeComplete, ProxyEndPoint, state);
return AsyncResult;
}
return null;
} }
/// <summary> /// <summary>
...@@ -369,8 +383,8 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -369,8 +383,8 @@ namespace Titanium.Web.Proxy.ProxySocket
this.Close(); this.Close();
ToThrow = error; ToThrow = error;
CallBack?.Invoke(AsyncResult);
AsyncResult.Reset(); AsyncResult.Reset();
CallBack?.Invoke(AsyncResult);
} }
/// <summary> /// <summary>
...@@ -389,17 +403,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -389,17 +403,7 @@ namespace Titanium.Web.Proxy.ProxySocket
/// Gets or sets a user-defined object. /// Gets or sets a user-defined object.
/// </summary> /// </summary>
/// <value>The user-defined object.</value> /// <value>The user-defined object.</value>
private object State private object State { get; set; }
{
get
{
return _state;
}
set
{
_state = value;
}
}
/// <summary> /// <summary>
/// Gets or sets the username to use when authenticating with the proxy. /// Gets or sets the username to use when authenticating with the proxy.
...@@ -442,8 +446,6 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -442,8 +446,6 @@ namespace Titanium.Web.Proxy.ProxySocket
private int RemotePort { get; set; } private int RemotePort { get; set; }
// private variables // private variables
/// <summary>Holds the value of the State property.</summary>
private object _state;
/// <summary>Holds the value of the ProxyUser property.</summary> /// <summary>Holds the value of the ProxyUser property.</summary>
private string _proxyUser = string.Empty; private string _proxyUser = string.Empty;
......
...@@ -169,14 +169,17 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -169,14 +169,17 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception> /// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
private void Negotiate(byte[] connect, int length) private void Negotiate(byte[] connect, int length)
{ {
if (connect.Length < 2) if (connect == null)
throw new ArgumentException(); throw new ArgumentNullException(nameof(connect));
if (Server.Send(connect, 0, length, SocketFlags.None) < connect.Length) if (length < 2)
throw new ArgumentException(nameof(length));
if (Server.Send(connect, 0, length, SocketFlags.None) < length)
throw new SocketException(10054); throw new SocketException(10054);
byte[] buffer = ReadBytes(8); ReadBytes(connect, 8);
if (buffer[1] != 90) if (connect[1] != 90)
{ {
Server.Close(); Server.Close();
throw new ProxyException("Negotiation failed."); throw new ProxyException("Negotiation failed.");
...@@ -266,8 +269,9 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -266,8 +269,9 @@ namespace Titanium.Web.Proxy.ProxySocket
try try
{ {
BufferCount = 8;
Received = 0; Received = 0;
Server.BeginReceive(Buffer, 0, 8, SocketFlags.None, OnReceive, Server); Server.BeginReceive(Buffer, 0, BufferCount, SocketFlags.None, OnReceive, Server);
} }
catch (Exception e) catch (Exception e)
{ {
...@@ -296,7 +300,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -296,7 +300,7 @@ namespace Titanium.Web.Proxy.ProxySocket
} }
else else
{ {
Server.BeginReceive(Buffer, Received, Buffer.Length - Received, SocketFlags.None, OnReceive, Server.BeginReceive(Buffer, Received, BufferCount - Received, SocketFlags.None, OnReceive,
Server); Server);
} }
} }
...@@ -305,11 +309,5 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -305,11 +309,5 @@ namespace Titanium.Web.Proxy.ProxySocket
OnProtocolComplete(e); OnProtocolComplete(e);
} }
} }
private void OnProtocolComplete(Exception? exception)
{
ArrayPool<byte>.Shared.Return(Buffer);
ProtocolComplete(exception);
}
} }
} }
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
*/ */
using System; using System;
using System.Buffers;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
...@@ -68,19 +69,6 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -68,19 +69,6 @@ namespace Titanium.Web.Proxy.ProxySocket
buffer[1] = (byte)(port % 256); buffer[1] = (byte)(port % 256);
} }
/// <summary>
/// Converts a port number to an array of bytes.
/// </summary>
/// <param name="port">The port to convert.</param>
/// <returns>An array of two bytes that represents the specified port.</returns>
protected byte[] PortToBytes(int port)
{
byte[] ret = new byte[2];
ret[0] = (byte)(port / 256);
ret[1] = (byte)(port % 256);
return ret;
}
/// <summary> /// <summary>
/// Converts an IP address to an array of bytes. /// Converts an IP address to an array of bytes.
/// </summary> /// </summary>
...@@ -99,16 +87,17 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -99,16 +87,17 @@ namespace Titanium.Web.Proxy.ProxySocket
/// <summary> /// <summary>
/// Reads a specified number of bytes from the Server socket. /// Reads a specified number of bytes from the Server socket.
/// </summary> /// </summary>
/// <param name="buffer">The result buffer.</param>
/// <param name="count">The number of bytes to return.</param> /// <param name="count">The number of bytes to return.</param>
/// <returns>An array of bytes.</returns> /// <returns>An array of bytes.</returns>
/// <exception cref="ArgumentException">The number of bytes to read is invalid.</exception> /// <exception cref="ArgumentException">The number of bytes to read is invalid.</exception>
/// <exception cref="SocketException">An operating system error occurs while accessing the Socket.</exception> /// <exception cref="SocketException">An operating system error occurs while accessing the Socket.</exception>
/// <exception cref="ObjectDisposedException">The Socket has been closed.</exception> /// <exception cref="ObjectDisposedException">The Socket has been closed.</exception>
protected byte[] ReadBytes(int count) protected void ReadBytes(byte[] buffer, int count)
{ {
if (count <= 0) if (count <= 0)
throw new ArgumentException(); throw new ArgumentException();
byte[] buffer = new byte[count];
int received = 0; int received = 0;
while (received != count) while (received != count)
{ {
...@@ -120,8 +109,6 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -120,8 +109,6 @@ namespace Titanium.Web.Proxy.ProxySocket
received += recv; received += recv;
} }
return buffer;
} }
/// <summary> /// <summary>
...@@ -134,6 +121,7 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -134,6 +121,7 @@ namespace Titanium.Web.Proxy.ProxySocket
int recv = Server.EndReceive(ar); int recv = Server.EndReceive(ar);
if (recv <= 0) if (recv <= 0)
throw new SocketException(10054); throw new SocketException(10054);
Received += recv; Received += recv;
} }
...@@ -149,6 +137,16 @@ namespace Titanium.Web.Proxy.ProxySocket ...@@ -149,6 +137,16 @@ namespace Titanium.Web.Proxy.ProxySocket
throw new SocketException(10054); throw new SocketException(10054);
} }
protected virtual void OnProtocolComplete(Exception? exception)
{
if (Buffer != null)
{
ArrayPool<byte>.Shared.Return(Buffer);
}
ProtocolComplete(exception);
}
/// <summary> /// <summary>
/// Gets or sets the socket connection with the proxy server. /// Gets or sets the socket connection with the proxy server.
/// </summary> /// </summary>
......
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