Skip to content

Commit 6c4ba9e

Browse files
committedNov 19, 2023
Fix of WebSocket close status frame
1 parent 9da7a15 commit 6c4ba9e

13 files changed

+94
-23
lines changed
 

‎source/NetCoreServer/Buffer.cs

+12-4
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ public override string ToString()
7070
return ExtractString(0, _size);
7171
}
7272

73-
// Clear the current buffer and its offset
73+
/// <summary>
74+
/// Clear the current buffer and its offset
75+
/// </summary>
7476
public void Clear()
7577
{
7678
_size = 0;
@@ -127,7 +129,9 @@ public void Reserve(long capacity)
127129
}
128130
}
129131

130-
// Resize the current buffer
132+
/// <summary>
133+
/// Resize the current buffer
134+
/// </summary>
131135
public void Resize(long size)
132136
{
133137
Reserve(size);
@@ -136,9 +140,13 @@ public void Resize(long size)
136140
_offset = _size;
137141
}
138142

139-
// Shift the current buffer offset
143+
/// <summary>
144+
/// Shift the current buffer offset
145+
/// </summary>
140146
public void Shift(long offset) { _offset += offset; }
141-
// Unshift the current buffer offset
147+
/// <summary>
148+
/// Unshift the current buffer offset
149+
/// </summary>
142150
public void Unshift(long offset) { _offset -= offset; }
143151

144152
#endregion

‎source/NetCoreServer/IWebSocket.cs

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace NetCoreServer
44
{
5+
/// <summary>
6+
/// WebSocket interface
7+
/// </summary>
58
public interface IWebSocket
69
{
710
/// <summary>

‎source/NetCoreServer/NetCoreServer.csproj

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
5-
<Version>8.0.0.0</Version>
5+
<Version>8.0.1.0</Version>
66
<Authors>Ivan Shynkarenka</Authors>
77
<Copyright>Copyright (c) 2019-2023 Ivan Shynkarenka</Copyright>
88
<RepositoryUrl>https://github.com/chronoxor/NetCoreServer</RepositoryUrl>
@@ -15,6 +15,8 @@
1515
<PropertyGroup>
1616
<IncludeSymbols>true</IncludeSymbols>
1717
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
18+
<GenerateDocumentationFile>True</GenerateDocumentationFile>
19+
<NoWarn>1591</NoWarn>
1820
</PropertyGroup>
1921

2022
</Project>

‎source/NetCoreServer/SslServer.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@ private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)
386386

387387
#region Session management
388388

389-
// Server sessions
389+
/// <summary>
390+
/// Server sessions
391+
/// </summary>
390392
protected readonly ConcurrentDictionary<Guid, SslSession> Sessions = new ConcurrentDictionary<Guid, SslSession>();
391393

392394
/// <summary>

‎source/NetCoreServer/TcpServer.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,9 @@ private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)
376376

377377
#region Session management
378378

379-
// Server sessions
379+
/// <summary>
380+
/// Server sessions
381+
/// </summary>
380382
protected readonly ConcurrentDictionary<Guid, TcpSession> Sessions = new ConcurrentDictionary<Guid, TcpSession>();
381383

382384
/// <summary>

‎source/NetCoreServer/UdsServer.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,9 @@ private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)
282282

283283
#region Session management
284284

285-
// Server sessions
285+
/// <summary>
286+
/// Server sessions
287+
/// </summary>
286288
protected readonly ConcurrentDictionary<Guid, UdsSession> Sessions = new ConcurrentDictionary<Guid, UdsSession>();
287289

288290
/// <summary>

‎source/NetCoreServer/WebSocket.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ public class WebSocket : IWebSocket
1313
{
1414
private readonly IWebSocket _wsHandler;
1515

16+
/// <summary>
17+
/// Initialize a new WebSocket
18+
/// </summary>
19+
/// <param name="wsHandler">WebSocket handler</param>
1620
public WebSocket(IWebSocket wsHandler) { _wsHandler = wsHandler; ClearWsBuffers(); InitWsNonce(); }
1721

1822
/// <summary>
@@ -253,7 +257,7 @@ public bool PerformServerUpgrade(HttpRequest request, HttpResponse response)
253257
/// <param name="status">WebSocket status (default is 0)</param>
254258
public void PrepareSendFrame(byte opcode, bool mask, ReadOnlySpan<byte> buffer, int status = 0)
255259
{
256-
bool storeWSCloseStatus = ((opcode & WS_CLOSE) == WS_CLOSE) && (buffer.Length > 0);
260+
bool storeWSCloseStatus = (opcode & WS_CLOSE) == WS_CLOSE;
257261
long size = storeWSCloseStatus ? (buffer.Length + 2) : buffer.Length;
258262

259263
// Clear the previous WebSocket send buffer
@@ -297,13 +301,13 @@ public void PrepareSendFrame(byte opcode, bool mask, ReadOnlySpan<byte> buffer,
297301
if (storeWSCloseStatus)
298302
{
299303
index += 2;
300-
WsSendBuffer.Append((byte)((status >> 8) & 0xFF));
301-
WsSendBuffer.Append((byte)(status & 0xFF));
304+
WsSendBuffer.Data[offset + 0] = (byte)(((status >> 8) & 0xFF) ^ WsSendMask[0]);
305+
WsSendBuffer.Data[offset + 1] = (byte)((status & 0xFF) ^ WsSendMask[1]);
302306
}
303307

304308
// Mask WebSocket frame content
305309
for (int i = index; i < size; i++)
306-
WsSendBuffer.Data[offset + i] = (byte)(buffer[i] ^ WsSendMask[i % 4]);
310+
WsSendBuffer.Data[offset + i] = (byte)(buffer[i - index] ^ WsSendMask[i % 4]);
307311
}
308312

309313
/// <summary>
@@ -470,7 +474,7 @@ public void PrepareReceiveFrame(byte[] buffer, long offset, long size)
470474
int status = 1000;
471475

472476
// Read WebSocket close status
473-
if (WsReceiveFinalBuffer.Size > 2)
477+
if (WsReceiveFinalBuffer.Size >= 2)
474478
{
475479
sindex += 2;
476480
status = ((WsReceiveFinalBuffer[0] << 8) | (WsReceiveFinalBuffer[1] << 0));

‎source/NetCoreServer/WsClient.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,18 @@ public class WsClient : HttpClient, IWebSocket
4545

4646
public override bool Connect() { _syncConnect = true; return base.Connect(); }
4747
public override bool ConnectAsync() { _syncConnect = false; return base.ConnectAsync(); }
48-
public virtual bool Close(int status) { SendClose(status, Span<byte>.Empty); base.Disconnect(); return true; }
49-
public virtual bool CloseAsync(int status) { SendCloseAsync(status, Span<byte>.Empty); base.DisconnectAsync(); return true; }
48+
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
49+
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
50+
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
51+
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
52+
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
53+
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.Disconnect(); return true; }
54+
public virtual bool CloseAsync(int status) => CloseAsync(status, Span<byte>.Empty);
55+
public virtual bool CloseAsync(int status, string text) => CloseAsync(status, Encoding.UTF8.GetBytes(text));
56+
public virtual bool CloseAsync(int status, ReadOnlySpan<char> text) => CloseAsync(status, Encoding.UTF8.GetBytes(text.ToArray()));
57+
public virtual bool CloseAsync(int status, byte[] buffer) => CloseAsync(status, buffer.AsSpan());
58+
public virtual bool CloseAsync(int status, byte[] buffer, long offset, long size) => CloseAsync(status, buffer.AsSpan((int)offset, (int)size));
59+
public virtual bool CloseAsync(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.DisconnectAsync(); return true; }
5060

5161
#endregion
5262

‎source/NetCoreServer/WsServer.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,16 @@ public class WsServer : HttpServer, IWebSocket
3737

3838
#region Session management
3939

40-
public virtual bool CloseAll(int status)
40+
public virtual bool CloseAll(int status) => CloseAll(status, Span<byte>.Empty);
41+
public virtual bool CloseAll(int status, string text) => CloseAll(status, Encoding.UTF8.GetBytes(text));
42+
public virtual bool CloseAll(int status, ReadOnlySpan<char> text) => CloseAll(status, Encoding.UTF8.GetBytes(text.ToArray()));
43+
public virtual bool CloseAll(int status, byte[] buffer) => CloseAll(status, buffer.AsSpan());
44+
public virtual bool CloseAll(int status, byte[] buffer, long offset, long size) => CloseAll(status, buffer.AsSpan((int)offset, (int)size));
45+
public virtual bool CloseAll(int status, ReadOnlySpan<byte> buffer)
4146
{
4247
lock (WebSocket.WsSendLock)
4348
{
44-
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, Span<byte>.Empty, status);
49+
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, buffer, status);
4550
if (!Multicast(WebSocket.WsSendBuffer.AsSpan()))
4651
return false;
4752

‎source/NetCoreServer/WsSession.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,19 @@ public class WsSession : HttpSession, IWebSocket
1212
{
1313
internal readonly WebSocket WebSocket;
1414

15+
/// <summary>
16+
/// Initialize a new WebSocket session
17+
/// </summary>
18+
/// <param name="server">WebSocket server</param>
1519
public WsSession(WsServer server) : base(server) { WebSocket = new WebSocket(this); }
1620

1721
// WebSocket connection methods
18-
public virtual bool Close(int status) { SendCloseAsync(status, Span<byte>.Empty); base.Disconnect(); return true; }
22+
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
23+
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
24+
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
25+
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
26+
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
27+
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendCloseAsync(status, buffer); base.Disconnect(); return true; }
1928

2029
#region WebSocket send text methods
2130

‎source/NetCoreServer/WssClient.cs

+12-2
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,18 @@ public class WssClient : HttpsClient, IWebSocket
4949

5050
public override bool Connect() { _syncConnect = true; return base.Connect(); }
5151
public override bool ConnectAsync() { _syncConnect = false; return base.ConnectAsync(); }
52-
public virtual bool Close(int status) { SendClose(status, Span<byte>.Empty); base.Disconnect(); return true; }
53-
public virtual bool CloseAsync(int status) { SendCloseAsync(status, Span<byte>.Empty); base.DisconnectAsync(); return true; }
52+
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
53+
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
54+
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
55+
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
56+
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
57+
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.Disconnect(); return true; }
58+
public virtual bool CloseAsync(int status) => CloseAsync(status, Span<byte>.Empty);
59+
public virtual bool CloseAsync(int status, string text) => CloseAsync(status, Encoding.UTF8.GetBytes(text));
60+
public virtual bool CloseAsync(int status, ReadOnlySpan<char> text) => CloseAsync(status, Encoding.UTF8.GetBytes(text.ToArray()));
61+
public virtual bool CloseAsync(int status, byte[] buffer) => CloseAsync(status, buffer.AsSpan());
62+
public virtual bool CloseAsync(int status, byte[] buffer, long offset, long size) => CloseAsync(status, buffer.AsSpan((int)offset, (int)size));
63+
public virtual bool CloseAsync(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.DisconnectAsync(); return true; }
5464

5565
#endregion
5666

‎source/NetCoreServer/WssServer.cs

+7-2
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,16 @@ public class WssServer : HttpsServer, IWebSocket
4141

4242
#region Session management
4343

44-
public virtual bool CloseAll(int status)
44+
public virtual bool CloseAll(int status) => CloseAll(status, Span<byte>.Empty);
45+
public virtual bool CloseAll(int status, string text) => CloseAll(status, Encoding.UTF8.GetBytes(text));
46+
public virtual bool CloseAll(int status, ReadOnlySpan<char> text) => CloseAll(status, Encoding.UTF8.GetBytes(text.ToArray()));
47+
public virtual bool CloseAll(int status, byte[] buffer) => CloseAll(status, buffer.AsSpan());
48+
public virtual bool CloseAll(int status, byte[] buffer, long offset, long size) => CloseAll(status, buffer.AsSpan((int)offset, (int)size));
49+
public virtual bool CloseAll(int status, ReadOnlySpan<byte> buffer)
4550
{
4651
lock (WebSocket.WsSendLock)
4752
{
48-
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, Span<byte>.Empty, status);
53+
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, buffer, status);
4954
if (!Multicast(WebSocket.WsSendBuffer.AsSpan()))
5055
return false;
5156

‎source/NetCoreServer/WssSession.cs

+10-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,19 @@ public class WssSession : HttpsSession, IWebSocket
1212
{
1313
internal readonly WebSocket WebSocket;
1414

15+
/// <summary>
16+
/// Initialize a new WebSocket session
17+
/// </summary>
18+
/// <param name="server">WebSocket server</param>
1519
public WssSession(WssServer server) : base(server) { WebSocket = new WebSocket(this); }
1620

1721
// WebSocket connection methods
18-
public virtual bool Close(int status) { SendCloseAsync(status, Span<byte>.Empty); base.Disconnect(); return true; }
22+
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
23+
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
24+
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
25+
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
26+
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
27+
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendCloseAsync(status, buffer); base.Disconnect(); return true; }
1928

2029
#region WebSocket send text methods
2130

0 commit comments

Comments
 (0)
Please sign in to comment.