Skip to content

Commit 880627a

Browse files
committed
[修改] Client/ClientProxy/ClientEngine 模块增加 XML 文档注释,扩展连接器功能(SocketConnector 支持 DNS、ProxyConnectorBase 可自定义连接器)
1 parent 0816b47 commit 880627a

16 files changed

Lines changed: 425 additions & 26 deletions

File tree

src/GameFrameX.SuperSocket.Client.Proxy/HttpConnector.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
namespace GameFrameX.SuperSocket.Client.Proxy
77
{
8+
/// <summary>
9+
/// Represents a connector for HTTP proxy connections.
10+
/// </summary>
811
public class HttpConnector : ProxyConnectorBase
912
{
1013
private const string _requestTemplate = "CONNECT {0}:{1} HTTP/1.1\r\nHost: {0}:{1}\r\nProxy-Connection: Keep-Alive\r\n";
@@ -13,18 +16,39 @@ public class HttpConnector : ProxyConnectorBase
1316
private string _username;
1417
private string _password;
1518

19+
/// <summary>
20+
/// Initializes a new instance of the <see cref="HttpConnector"/> class with the specified proxy endpoint.
21+
/// </summary>
22+
/// <param name="proxyEndPoint">The endpoint of the HTTP proxy server.</param>
1623
public HttpConnector(EndPoint proxyEndPoint)
1724
: base(proxyEndPoint)
1825
{
1926
}
2027

28+
/// <summary>
29+
/// Initializes a new instance of the <see cref="HttpConnector"/> class with the specified proxy endpoint, username, and password.
30+
/// </summary>
31+
/// <param name="proxyEndPoint">The endpoint of the HTTP proxy server.</param>
32+
/// <param name="username">The username for authentication.</param>
33+
/// <param name="password">The password for authentication.</param>
2134
public HttpConnector(EndPoint proxyEndPoint, string username, string password)
2235
: this(proxyEndPoint)
2336
{
2437
_username = username;
2538
_password = password;
2639
}
2740

41+
/// <summary>
42+
/// Connects to the specified remote endpoint through the HTTP proxy.
43+
/// </summary>
44+
/// <param name="remoteEndPoint">The remote endpoint to connect to.</param>
45+
/// <param name="state">The connection state from the previous connector.</param>
46+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
47+
/// <returns>A task representing the asynchronous connection operation. The result contains information about the connection status.</returns>
48+
/// <remarks>
49+
/// This method establishes a connection to the remote endpoint through the HTTP proxy using the CONNECT method.
50+
/// It supports both DNS and IP endpoint types and handles proxy authentication if credentials are provided.
51+
/// </remarks>
2852
protected override async ValueTask<ConnectState> ConnectProxyAsync(EndPoint remoteEndPoint, ConnectState state, CancellationToken cancellationToken)
2953
{
3054
var encoding = Encoding.ASCII;
@@ -84,6 +108,16 @@ await connection.SendAsync((writer) =>
84108
return state;
85109
}
86110

111+
/// <summary>
112+
/// Processes the HTTP response from the proxy server.
113+
/// </summary>
114+
/// <param name="p">The text package containing the HTTP response.</param>
115+
/// <param name="message">When this method returns, contains an error message if the response is invalid; otherwise, an empty string.</param>
116+
/// <returns><c>true</c> if the response indicates a successful connection; otherwise, <c>false</c>.</returns>
117+
/// <remarks>
118+
/// A successful response should have a status code in the 2xx range (200-299).
119+
/// This method validates the format of the HTTP response and extracts the status code.
120+
/// </remarks>
87121
private bool HandleResponse(TextPackageInfo p, out string message)
88122
{
89123
message = string.Empty;

src/GameFrameX.SuperSocket.Client.Proxy/ProxyConnectorBase.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,53 @@
22

33
namespace GameFrameX.SuperSocket.Client.Proxy
44
{
5+
/// <summary>
6+
/// Provides a base class for proxy connectors.
7+
/// </summary>
58
public abstract class ProxyConnectorBase : ConnectorBase
69
{
710
private EndPoint _proxyEndPoint;
811

12+
/// <summary>
13+
/// Initializes a new instance of the <see cref="ProxyConnectorBase"/> class with the specified proxy endpoint.
14+
/// </summary>
15+
/// <param name="proxyEndPoint">The endpoint of the proxy server.</param>
916
public ProxyConnectorBase(EndPoint proxyEndPoint)
1017
{
1118
_proxyEndPoint = proxyEndPoint;
1219
}
1320

21+
/// <summary>
22+
/// Connects to the specified remote endpoint through the proxy.
23+
/// </summary>
24+
/// <param name="remoteEndPoint">The remote endpoint to connect to.</param>
25+
/// <param name="state">The connection state.</param>
26+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
27+
/// <returns>A task representing the asynchronous connection operation.</returns>
1428
protected abstract ValueTask<ConnectState> ConnectProxyAsync(EndPoint remoteEndPoint, ConnectState state, CancellationToken cancellationToken);
1529

30+
/// <summary>
31+
/// Creates the default connector for the proxy connection.
32+
/// </summary>
33+
protected virtual IConnector CreateDefaultConnector()
34+
{
35+
return new SocketConnector();
36+
}
37+
38+
/// <summary>
39+
/// Establishes a connection to the specified remote endpoint through the proxy.
40+
/// </summary>
41+
/// <param name="remoteEndPoint">The remote endpoint to connect to.</param>
42+
/// <param name="state">The connection state.</param>
43+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
44+
/// <returns>A task representing the asynchronous connection operation. The result contains information about the connection status.</returns>
45+
/// <remarks>
46+
/// This method first establishes a connection to the proxy server, and then calls <see cref="ConnectProxyAsync"/> to
47+
/// establish a connection to the remote endpoint through the proxy.
48+
/// </remarks>
1649
protected override async ValueTask<ConnectState> ConnectAsync(EndPoint remoteEndPoint, ConnectState state, CancellationToken cancellationToken)
1750
{
18-
var socketConnector = new SocketConnector() as IConnector;
51+
var socketConnector = CreateDefaultConnector();
1952
var proxyEndPoint = _proxyEndPoint;
2053

2154
ConnectState result;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
namespace GameFrameX.SuperSocket.Client.Proxy
22
{
3+
/// <summary>
4+
/// Specifies the types of proxy servers supported.
5+
/// </summary>
36
public enum ProxyType
47
{
8+
/// <summary>
9+
/// HTTP proxy.
10+
/// </summary>
511
Http,
12+
13+
/// <summary>
14+
/// SOCKS4 proxy.
15+
/// </summary>
616
Socks4,
17+
18+
/// <summary>
19+
/// SOCKS4a proxy.
20+
/// </summary>
721
Socks4a,
22+
23+
/// <summary>
24+
/// SOCKS5 proxy.
25+
/// </summary>
826
Socks5
927
}
1028
}

src/GameFrameX.SuperSocket.Client.Proxy/Socks4Connector.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,18 @@
22

33
namespace GameFrameX.SuperSocket.Client.Proxy
44
{
5+
/// <summary>
6+
/// Represents a connector for SOCKS4 proxy connections.
7+
/// </summary>
58
public class Socks4Connector : ConnectorBase
69
{
10+
/// <summary>
11+
/// Connects to the specified remote endpoint through the SOCKS4 proxy.
12+
/// </summary>
13+
/// <param name="remoteEndPoint">The remote endpoint to connect to.</param>
14+
/// <param name="state">The connection state.</param>
15+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
16+
/// <returns>A task representing the asynchronous connection operation.</returns>
717
protected override ValueTask<ConnectState> ConnectAsync(EndPoint remoteEndPoint, ConnectState state, CancellationToken cancellationToken)
818
{
919
throw new NotImplementedException();

src/GameFrameX.SuperSocket.Client.Proxy/Socks5Connector.cs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ public Socks5Connector(EndPoint proxyEndPoint, string username, string password)
4747
_authenHandshakeRequest = AuthenHandshake;
4848
}
4949

50+
/// <summary>
51+
/// Connects to the specified remote endpoint through the SOCKS5 proxy.
52+
/// </summary>
53+
/// <param name="remoteEndPoint">The remote endpoint to connect to.</param>
54+
/// <param name="state">The connection state from the previous connector.</param>
55+
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
5056
protected override async ValueTask<ConnectState> ConnectProxyAsync(EndPoint remoteEndPoint, ConnectState state, CancellationToken cancellationToken)
5157
{
5258
var connection = state.CreateConnection(new ConnectionOptions { ReadAsDemand = true });
@@ -283,35 +289,76 @@ enum Socket5ResponseType
283289
AuthEndPoint,
284290
}
285291

292+
/// <summary>
293+
/// Represents the address type used in SOCKS5 protocol.
294+
/// </summary>
286295
public class Socks5Address
287296
{
297+
/// <summary>
298+
/// Gets or sets the IP address.
299+
/// </summary>
288300
public IPAddress IPAddress { get; set; }
289301

302+
/// <summary>
303+
/// Gets or sets the domain name.
304+
/// </summary>
290305
public string DomainName { get; set; }
291306
}
292307

308+
/// <summary>
309+
/// Represents a SOCKS5 packet.
310+
/// </summary>
293311
public class Socks5Pack
294312
{
313+
/// <summary>
314+
/// Gets or sets the version of the SOCKS5 protocol.
315+
/// </summary>
295316
public byte Version { get; set; }
296317

318+
/// <summary>
319+
/// Gets or sets the status of the SOCKS5 connection.
320+
/// </summary>
297321
public byte Status { get; set; }
298322

323+
/// <summary>
324+
/// Gets or sets the reserved byte.
325+
/// </summary>
299326
public byte Reserve { get; set; }
300327

328+
/// <summary>
329+
/// Gets or sets the destination address.
330+
/// </summary>
301331
public Socks5Address DestAddr { get; set; }
302332

333+
/// <summary>
334+
/// Gets or sets the destination port.
335+
/// </summary>
303336
public short DestPort { get; set; }
304337
}
305338

339+
/// <summary>
340+
/// Represents a pipeline filter for SOCKS5 authentication.
341+
/// </summary>
306342
public class Socks5AuthPipelineFilter : FixedSizePipelineFilter<Socks5Pack>
307343
{
344+
/// <summary>
345+
/// Gets or sets the authentication step.
346+
/// </summary>
308347
public int AuthStep { get; set; }
309348

349+
/// <summary>
350+
/// Initializes a new instance of the <see cref="Socks5AuthPipelineFilter"/> class.
351+
/// </summary>
310352
public Socks5AuthPipelineFilter()
311353
: base(2)
312354
{
355+
313356
}
314357

358+
/// <summary>
359+
/// Gets the body length from the header.
360+
/// </summary>
361+
/// <param name="buffer">The buffer containing the header.</param>
315362
protected override Socks5Pack DecodePackage(ref ReadOnlySequence<byte> buffer)
316363
{
317364
var reader = new SequenceReader<byte>(buffer);
@@ -331,13 +378,24 @@ protected override Socks5Pack DecodePackage(ref ReadOnlySequence<byte> buffer)
331378
}
332379
}
333380

381+
/// <summary>
382+
/// Represents a pipeline filter for SOCKS5 address.
383+
/// </summary>
334384
public class Socks5AddressPipelineFilter : FixedHeaderPipelineFilter<Socks5Pack>
335385
{
386+
/// <summary>
387+
/// Initializes a new instance of the <see cref="Socks5AddressPipelineFilter"/> class.
388+
/// </summary>
336389
public Socks5AddressPipelineFilter()
337390
: base(5)
338391
{
392+
339393
}
340394

395+
/// <summary>
396+
/// Gets the body length from the header.
397+
/// </summary>
398+
/// <param name="buffer">The buffer containing the header.</param>
341399
protected override int GetBodyLengthFromHeader(ref ReadOnlySequence<byte> buffer)
342400
{
343401
var reader = new SequenceReader<byte>(buffer);
@@ -359,6 +417,10 @@ protected override int GetBodyLengthFromHeader(ref ReadOnlySequence<byte> buffer
359417
throw new Exception($"Unsupported addressType: {addressType}");
360418
}
361419

420+
/// <summary>
421+
/// Decodes the package from the buffer.
422+
/// </summary>
423+
/// <param name="buffer">The buffer containing the package data.</param>
362424
protected override Socks5Pack DecodePackage(ref ReadOnlySequence<byte> buffer)
363425
{
364426
var reader = new SequenceReader<byte>(buffer);

src/GameFrameX.SuperSocket.Client/ConnectState.cs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1+
using System;
2+
using System.IO;
13
using System.Net.Sockets;
24
using GameFrameX.SuperSocket.Connection;
35
using GameFrameX.SuperSocket.Connection.Sockets;
46
using Microsoft.Extensions.ObjectPool;
57

68
namespace GameFrameX.SuperSocket.Client
79
{
10+
/// <summary>
11+
/// Represents the state of a connection, including its result, socket, and stream.
12+
/// </summary>
813
public class ConnectState
914
{
15+
/// <summary>
16+
/// Initializes a new instance of the <see cref="ConnectState"/> class.
17+
/// </summary>
1018
public ConnectState()
1119
{
1220
}
@@ -16,16 +24,34 @@ private ConnectState(bool cancelled)
1624
Cancelled = cancelled;
1725
}
1826

27+
/// <summary>
28+
/// Gets or sets a value indicating whether the connection was successful.
29+
/// </summary>
1930
public bool Result { get; set; }
2031

32+
/// <summary>
33+
/// Gets a value indicating whether the connection was cancelled.
34+
/// </summary>
2135
public bool Cancelled { get; private set; }
2236

37+
/// <summary>
38+
/// Gets or sets the exception that occurred during the connection attempt, if any.
39+
/// </summary>
2340
public Exception Exception { get; set; }
2441

42+
/// <summary>
43+
/// Gets or sets the socket associated with the connection.
44+
/// </summary>
2545
public Socket Socket { get; set; }
2646

47+
/// <summary>
48+
/// Gets or sets the stream associated with the connection.
49+
/// </summary>
2750
public Stream Stream { get; set; }
2851

52+
/// <summary>
53+
/// Represents a connection state that indicates the connection was cancelled.
54+
/// </summary>
2955
public static readonly ConnectState CancelledState = new ConnectState(false);
3056

3157
private static Lazy<ObjectPool<SocketSender>> _socketSenderPool = new Lazy<ObjectPool<SocketSender>>(() =>
@@ -35,14 +61,19 @@ private ConnectState(bool cancelled)
3561
return pool;
3662
});
3763

64+
/// <summary>
65+
/// Creates a connection object based on the current state.
66+
/// </summary>
67+
/// <param name="connectionOptions">The connection options to use.</param>
68+
/// <returns>An <see cref="IConnection"/> object representing the connection.</returns>
3869
public IConnection CreateConnection(ConnectionOptions connectionOptions)
3970
{
4071
var stream = this.Stream;
4172
var socket = this.Socket;
4273

4374
if (stream != null)
4475
{
45-
return new StreamPipeConnection(stream, socket.RemoteEndPoint, socket.LocalEndPoint, connectionOptions);
76+
return new StreamPipeConnection(stream , socket.RemoteEndPoint, socket.LocalEndPoint, connectionOptions);
4677
}
4778
else
4879
{

0 commit comments

Comments
 (0)