Skip to content

Commit dbcafd9

Browse files
committed
[修改] WebSocket 核心模块增加 XML 文档注释,优化编码器、管线过滤器、压缩扩展和帧读取器
1 parent ec96b00 commit dbcafd9

22 files changed

Lines changed: 764 additions & 20 deletions

src/GameFrameX.SuperSocket.WebSocket/CloseReason.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,59 @@
33

44
namespace GameFrameX.SuperSocket.WebSocket
55
{
6+
/// <summary>
7+
/// Represents the reasons for closing a WebSocket connection.
8+
/// </summary>
69
public enum CloseReason : short
710
{
11+
/// <summary>
12+
/// Indicates a normal closure of the WebSocket connection.
13+
/// </summary>
814
NormalClosure = 1000,
15+
16+
/// <summary>
17+
/// Indicates that the WebSocket connection is going away.
18+
/// </summary>
919
GoingAway = 1001,
20+
21+
/// <summary>
22+
/// Indicates a protocol error occurred.
23+
/// </summary>
1024
ProtocolError = 1002,
25+
26+
/// <summary>
27+
/// Indicates that the data received is not acceptable.
28+
/// </summary>
1129
NotAcceptableData = 1003,
30+
31+
/// <summary>
32+
/// Indicates that the frame received is too large.
33+
/// </summary>
1234
TooLargeFrame = 1009,
35+
36+
/// <summary>
37+
/// Indicates that the data received contains invalid UTF-8.
38+
/// </summary>
1339
InvalidUTF8 = 1007,
40+
41+
/// <summary>
42+
/// Indicates a policy violation occurred.
43+
/// </summary>
1444
ViolatePolicy = 1008,
45+
46+
/// <summary>
47+
/// Indicates that the WebSocket extension does not match.
48+
/// </summary>
1549
ExtensionNotMatch = 1010,
50+
51+
/// <summary>
52+
/// Indicates an unexpected condition caused the closure.
53+
/// </summary>
1654
UnexpectedCondition = 1011,
55+
56+
/// <summary>
57+
/// Indicates that no status code was provided.
58+
/// </summary>
1759
NoStatusCode = 1005
1860
}
1961
}

src/GameFrameX.SuperSocket.WebSocket/CloseStatus.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,24 @@
33

44
namespace GameFrameX.SuperSocket.WebSocket
55
{
6+
/// <summary>
7+
/// Represents the status of a WebSocket close operation.
8+
/// </summary>
69
public class CloseStatus
710
{
11+
/// <summary>
12+
/// Gets or sets the reason for the WebSocket close operation.
13+
/// </summary>
814
public CloseReason Reason { get; set; }
915

16+
/// <summary>
17+
/// Gets or sets the reason text for the WebSocket close operation.
18+
/// </summary>
1019
public string ReasonText { get; set; }
1120

21+
/// <summary>
22+
/// Gets or sets a value indicating whether the close operation was initiated by the remote endpoint.
23+
/// </summary>
1224
public bool RemoteInitiated { get; set; }
1325
}
1426
}

src/GameFrameX.SuperSocket.WebSocket/ExtensionMethods.cs

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

66
namespace GameFrameX.SuperSocket.WebSocket
77
{
8+
/// <summary>
9+
/// Extension methods for WebSocket implementation.
10+
/// </summary>
811
public static partial class ExtensionMethods
912
{
1013
private readonly static char[] m_CrCf = new char[] { '\r', '\n' };
@@ -53,6 +56,11 @@ public static void AppendWithCrCf(this StringBuilder builder)
5356
builder.Append(m_CrCf);
5457
}
5558

59+
/// <summary>
60+
/// Creates a copy of the given ReadOnlySequence.
61+
/// </summary>
62+
/// <param name="seq">The sequence to copy.</param>
63+
/// <returns>A new ReadOnlySequence that is a copy of the input sequence.</returns>
5664
internal static ReadOnlySequence<byte> CopySequence(ref this ReadOnlySequence<byte> seq)
5765
{
5866
SequenceSegment head = null;
@@ -71,6 +79,11 @@ internal static ReadOnlySequence<byte> CopySequence(ref this ReadOnlySequence<by
7179
return new ReadOnlySequence<byte>(head, 0, tail, tail.Memory.Length);
7280
}
7381

82+
/// <summary>
83+
/// Destructs the given ReadOnlySequence into its head and tail segments.
84+
/// </summary>
85+
/// <param name="first">The sequence to destruct.</param>
86+
/// <returns>A tuple containing the head and tail segments of the sequence.</returns>
7487
internal static (SequenceSegment, SequenceSegment) DestructSequence(ref this ReadOnlySequence<byte> first)
7588
{
7689
SequenceSegment head = first.Start.GetObject() as SequenceSegment;
@@ -90,6 +103,12 @@ internal static (SequenceSegment, SequenceSegment) DestructSequence(ref this Rea
90103
return (head, tail);
91104
}
92105

106+
/// <summary>
107+
/// Concatenates two ReadOnlySequences into a single sequence.
108+
/// </summary>
109+
/// <param name="first">The first sequence.</param>
110+
/// <param name="second">The second sequence.</param>
111+
/// <returns>A new ReadOnlySequence that is the concatenation of the two input sequences.</returns>
93112
internal static ReadOnlySequence<byte> ConcatSequence(ref this ReadOnlySequence<byte> first, ref ReadOnlySequence<byte> second)
94113
{
95114
var (head, tail) = first.DestructSequence();
@@ -105,6 +124,12 @@ internal static ReadOnlySequence<byte> ConcatSequence(ref this ReadOnlySequence<
105124
return new ReadOnlySequence<byte>(head, 0, tail, tail.Memory.Length);
106125
}
107126

127+
/// <summary>
128+
/// Concatenates a ReadOnlySequence with a single SequenceSegment.
129+
/// </summary>
130+
/// <param name="first">The sequence to concatenate.</param>
131+
/// <param name="segment">The segment to append to the sequence.</param>
132+
/// <returns>A new ReadOnlySequence that includes the appended segment.</returns>
108133
internal static ReadOnlySequence<byte> ConcatSequence(ref this ReadOnlySequence<byte> first, SequenceSegment segment)
109134
{
110135
var (head, tail) = first.DestructSequence();

src/GameFrameX.SuperSocket.WebSocket/Extensions/Compression/ReadOnlySequenceStream.cs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,71 @@
22

33
namespace GameFrameX.SuperSocket.WebSocket.Extensions.Compression
44
{
5+
/// <summary>
6+
/// Represents a read-only stream that reads data from a <see cref="ReadOnlySequence{T}"/>.
7+
/// </summary>
58
class ReadOnlySequenceStream : Stream
69
{
710
private ReadOnlySequence<byte> _sequence;
811

12+
/// <summary>
13+
/// Gets a value indicating whether the stream supports reading. Always returns true.
14+
/// </summary>
915
public override bool CanRead => true;
1016

17+
/// <summary>
18+
/// Gets a value indicating whether the stream supports seeking. Always returns false.
19+
/// </summary>
1120
public override bool CanSeek => false;
1221

22+
/// <summary>
23+
/// Gets a value indicating whether the stream supports writing. Always returns false.
24+
/// </summary>
1325
public override bool CanWrite => false;
1426

1527
private long _length;
1628

29+
/// <summary>
30+
/// Gets the length of the stream.
31+
/// </summary>
1732
public override long Length => _length;
1833

1934
/// <summary>
2035
/// Gets or sets the position within the stream. Not implemented.
2136
/// </summary>
2237
/// <exception cref="NotImplementedException">Always thrown.</exception>
23-
public override long Position
24-
{
25-
get { throw new NotImplementedException(); }
26-
set { throw new NotImplementedException(); }
27-
}
38+
public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
2839

40+
/// <summary>
41+
/// Initializes a new instance of the <see cref="ReadOnlySequenceStream"/> class with the specified sequence.
42+
/// </summary>
43+
/// <param name="sequence">The read-only sequence to read data from.</param>
2944
public ReadOnlySequenceStream(ReadOnlySequence<byte> sequence)
3045
{
3146
_sequence = sequence;
3247
_length = sequence.Length;
3348
}
3449

50+
/// <summary>
51+
/// Flushes the stream. Not supported.
52+
/// </summary>
53+
/// <exception cref="NotSupportedException">Always thrown.</exception>
3554
public override void Flush()
3655
{
3756
throw new NotSupportedException();
3857
}
3958

59+
/// <summary>
60+
/// Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
61+
/// </summary>
62+
/// <param name="buffer">The buffer to read data into.</param>
63+
/// <param name="offset">The zero-based byte offset in the buffer at which to begin storing the data read from the stream.</param>
64+
/// <param name="count">The maximum number of bytes to read.</param>
65+
/// <returns>The total number of bytes read into the buffer.</returns>
4066
public override int Read(byte[] buffer, int offset, int count)
4167
{
4268
var firstSpan = _sequence.FirstSpan;
43-
69+
4470
if (firstSpan.IsEmpty)
4571
return 0;
4672

@@ -52,16 +78,35 @@ public override int Read(byte[] buffer, int offset, int count)
5278
return len;
5379
}
5480

81+
/// <summary>
82+
/// Sets the position within the stream. Not supported.
83+
/// </summary>
84+
/// <param name="offset">The byte offset relative to the <paramref name="origin"/>.</param>
85+
/// <param name="origin">A value of type <see cref="SeekOrigin"/> indicating the reference point used to obtain the new position.</param>
86+
/// <returns>Always throws a <see cref="NotSupportedException"/>.</returns>
87+
/// <exception cref="NotSupportedException">Always thrown.</exception>
5588
public override long Seek(long offset, SeekOrigin origin)
5689
{
5790
throw new NotSupportedException();
5891
}
5992

93+
/// <summary>
94+
/// Sets the length of the stream. Not supported.
95+
/// </summary>
96+
/// <param name="value">The desired length of the stream.</param>
97+
/// <exception cref="NotSupportedException">Always thrown.</exception>
6098
public override void SetLength(long value)
6199
{
62100
throw new NotSupportedException();
63101
}
64102

103+
/// <summary>
104+
/// Writes a sequence of bytes to the current stream. Not supported.
105+
/// </summary>
106+
/// <param name="buffer">The buffer containing data to write.</param>
107+
/// <param name="offset">The zero-based byte offset in the buffer at which to begin copying bytes to the stream.</param>
108+
/// <param name="count">The number of bytes to write to the stream.</param>
109+
/// <exception cref="NotSupportedException">Always thrown.</exception>
65110
public override void Write(byte[] buffer, int offset, int count)
66111
{
67112
throw new NotSupportedException();

src/GameFrameX.SuperSocket.WebSocket/Extensions/Compression/WebSocketPerMessageCompressionExtension.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@
88
namespace GameFrameX.SuperSocket.WebSocket.Extensions.Compression
99
{
1010
/// <summary>
11-
/// WebSocket Per-Message Compression Extension
12-
/// https://tools.ietf.org/html/rfc7692
11+
/// Implements the WebSocket Per-Message Compression Extension as defined in RFC 7692.
1312
/// </summary>
1413
public class WebSocketPerMessageCompressionExtension : IWebSocketExtension
1514
{
15+
/// <summary>
16+
/// Gets the name of the WebSocket Per-Message Compression Extension.
17+
/// </summary>
1618
public string Name => PMCE;
1719

20+
/// <summary>
21+
/// The name of the Per-Message Compression Extension.
22+
/// </summary>
1823
public const string PMCE = "permessage-deflate";
1924

2025
private const int _deflateBufferSize = 1024 * 1024 * 4;
@@ -24,6 +29,10 @@ public class WebSocketPerMessageCompressionExtension : IWebSocketExtension
2429
private static readonly byte[] LAST_FOUR_OCTETS = new byte[] { 0x00, 0x00, 0xFF, 0xFF };
2530
private static readonly ArrayPool<byte> _arrayPool = ArrayPool<byte>.Shared;
2631

32+
/// <summary>
33+
/// Decodes a WebSocket package by decompressing its data.
34+
/// </summary>
35+
/// <param name="package">The WebSocket package to decode.</param>
2736
public void Decode(WebSocketPackage package)
2837
{
2938
if (!package.RSV1)
@@ -58,22 +67,30 @@ public void Decode(WebSocketPackage package)
5867
package.Data = new ReadOnlySequence<byte>(head, 0, tail, tail.Memory.Length);
5968
}
6069

70+
/// <summary>
71+
/// Encodes a WebSocket package by compressing its data.
72+
/// </summary>
73+
/// <param name="package">The WebSocket package to encode.</param>
6174
public void Encode(WebSocketPackage package)
6275
{
6376
package.RSV1 = true;
6477

6578
if (package.Data.IsEmpty)
6679
EncodeTextMessage(package);
6780
else
68-
EncodeDataMessage(package);
81+
EncodeDataMessage(package);
6982
}
7083

84+
/// <summary>
85+
/// Encodes a text message in a WebSocket package using compression.
86+
/// </summary>
87+
/// <param name="package">The WebSocket package containing the text message.</param>
7188
private void EncodeTextMessage(WebSocketPackage package)
7289
{
7390
var encoder = _encoding.GetEncoder();
7491
var text = package.Message.AsSpan();
7592

76-
var completed = false;
93+
var completed = false;
7794

7895
var outputStream = new WritableSequenceStream();
7996

@@ -85,7 +102,7 @@ private void EncodeTextMessage(WebSocketPackage package)
85102
Span<byte> span = buffer;
86103

87104
encoder.Convert(text, span, false, out int charsUsed, out int bytesUsed, out completed);
88-
105+
89106
if (charsUsed > 0)
90107
text = text.Slice(charsUsed);
91108

@@ -100,6 +117,10 @@ private void EncodeTextMessage(WebSocketPackage package)
100117
package.Data = data;
101118
}
102119

120+
/// <summary>
121+
/// Removes the last four octets from the compressed data sequence.
122+
/// </summary>
123+
/// <param name="data">The compressed data sequence.</param>
103124
private void RemoveLastFourOctets(ref ReadOnlySequence<byte> data)
104125
{
105126
var octetsLen = LAST_FOUR_OCTETS.Length;
@@ -122,6 +143,10 @@ private void RemoveLastFourOctets(ref ReadOnlySequence<byte> data)
122143
data = data.Slice(0, data.Length - octetsLen);
123144
}
124145

146+
/// <summary>
147+
/// Encodes a data message in a WebSocket package using compression.
148+
/// </summary>
149+
/// <param name="package">The WebSocket package containing the data message.</param>
125150
private void EncodeDataMessage(WebSocketPackage package)
126151
{
127152
var data = package.Data;

0 commit comments

Comments
 (0)