Skip to content

Commit

Permalink
Fix of WebSocket close status frame
Browse files Browse the repository at this point in the history
  • Loading branch information
chronoxor committed Nov 19, 2023
1 parent 9da7a15 commit 6c4ba9e
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 23 deletions.
16 changes: 12 additions & 4 deletions source/NetCoreServer/Buffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ public override string ToString()
return ExtractString(0, _size);
}

// Clear the current buffer and its offset
/// <summary>
/// Clear the current buffer and its offset
/// </summary>
public void Clear()
{
_size = 0;
Expand Down Expand Up @@ -127,7 +129,9 @@ public void Reserve(long capacity)
}
}

// Resize the current buffer
/// <summary>
/// Resize the current buffer
/// </summary>
public void Resize(long size)
{
Reserve(size);
Expand All @@ -136,9 +140,13 @@ public void Resize(long size)
_offset = _size;
}

// Shift the current buffer offset
/// <summary>
/// Shift the current buffer offset
/// </summary>
public void Shift(long offset) { _offset += offset; }
// Unshift the current buffer offset
/// <summary>
/// Unshift the current buffer offset
/// </summary>
public void Unshift(long offset) { _offset -= offset; }

#endregion
Expand Down
3 changes: 3 additions & 0 deletions source/NetCoreServer/IWebSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace NetCoreServer
{
/// <summary>
/// WebSocket interface
/// </summary>
public interface IWebSocket
{
/// <summary>
Expand Down
4 changes: 3 additions & 1 deletion source/NetCoreServer/NetCoreServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Version>8.0.0.0</Version>
<Version>8.0.1.0</Version>
<Authors>Ivan Shynkarenka</Authors>
<Copyright>Copyright (c) 2019-2023 Ivan Shynkarenka</Copyright>
<RepositoryUrl>https://github.com/chronoxor/NetCoreServer</RepositoryUrl>
Expand All @@ -15,6 +15,8 @@
<PropertyGroup>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>

</Project>
4 changes: 3 additions & 1 deletion source/NetCoreServer/SslServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,9 @@ private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)

#region Session management

// Server sessions
/// <summary>
/// Server sessions
/// </summary>
protected readonly ConcurrentDictionary<Guid, SslSession> Sessions = new ConcurrentDictionary<Guid, SslSession>();

/// <summary>
Expand Down
4 changes: 3 additions & 1 deletion source/NetCoreServer/TcpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,9 @@ private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)

#region Session management

// Server sessions
/// <summary>
/// Server sessions
/// </summary>
protected readonly ConcurrentDictionary<Guid, TcpSession> Sessions = new ConcurrentDictionary<Guid, TcpSession>();

/// <summary>
Expand Down
4 changes: 3 additions & 1 deletion source/NetCoreServer/UdsServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ private void OnAsyncCompleted(object sender, SocketAsyncEventArgs e)

#region Session management

// Server sessions
/// <summary>
/// Server sessions
/// </summary>
protected readonly ConcurrentDictionary<Guid, UdsSession> Sessions = new ConcurrentDictionary<Guid, UdsSession>();

/// <summary>
Expand Down
14 changes: 9 additions & 5 deletions source/NetCoreServer/WebSocket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ public class WebSocket : IWebSocket
{
private readonly IWebSocket _wsHandler;

/// <summary>
/// Initialize a new WebSocket
/// </summary>
/// <param name="wsHandler">WebSocket handler</param>
public WebSocket(IWebSocket wsHandler) { _wsHandler = wsHandler; ClearWsBuffers(); InitWsNonce(); }

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

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

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

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

// Read WebSocket close status
if (WsReceiveFinalBuffer.Size > 2)
if (WsReceiveFinalBuffer.Size >= 2)
{
sindex += 2;
status = ((WsReceiveFinalBuffer[0] << 8) | (WsReceiveFinalBuffer[1] << 0));
Expand Down
14 changes: 12 additions & 2 deletions source/NetCoreServer/WsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,18 @@ public class WsClient : HttpClient, IWebSocket

public override bool Connect() { _syncConnect = true; return base.Connect(); }
public override bool ConnectAsync() { _syncConnect = false; return base.ConnectAsync(); }
public virtual bool Close(int status) { SendClose(status, Span<byte>.Empty); base.Disconnect(); return true; }
public virtual bool CloseAsync(int status) { SendCloseAsync(status, Span<byte>.Empty); base.DisconnectAsync(); return true; }
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.Disconnect(); return true; }
public virtual bool CloseAsync(int status) => CloseAsync(status, Span<byte>.Empty);
public virtual bool CloseAsync(int status, string text) => CloseAsync(status, Encoding.UTF8.GetBytes(text));
public virtual bool CloseAsync(int status, ReadOnlySpan<char> text) => CloseAsync(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool CloseAsync(int status, byte[] buffer) => CloseAsync(status, buffer.AsSpan());
public virtual bool CloseAsync(int status, byte[] buffer, long offset, long size) => CloseAsync(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool CloseAsync(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.DisconnectAsync(); return true; }

#endregion

Expand Down
9 changes: 7 additions & 2 deletions source/NetCoreServer/WsServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,16 @@ public class WsServer : HttpServer, IWebSocket

#region Session management

public virtual bool CloseAll(int status)
public virtual bool CloseAll(int status) => CloseAll(status, Span<byte>.Empty);
public virtual bool CloseAll(int status, string text) => CloseAll(status, Encoding.UTF8.GetBytes(text));
public virtual bool CloseAll(int status, ReadOnlySpan<char> text) => CloseAll(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool CloseAll(int status, byte[] buffer) => CloseAll(status, buffer.AsSpan());
public virtual bool CloseAll(int status, byte[] buffer, long offset, long size) => CloseAll(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool CloseAll(int status, ReadOnlySpan<byte> buffer)
{
lock (WebSocket.WsSendLock)
{
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, Span<byte>.Empty, status);
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, buffer, status);
if (!Multicast(WebSocket.WsSendBuffer.AsSpan()))
return false;

Expand Down
11 changes: 10 additions & 1 deletion source/NetCoreServer/WsSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,19 @@ public class WsSession : HttpSession, IWebSocket
{
internal readonly WebSocket WebSocket;

/// <summary>
/// Initialize a new WebSocket session
/// </summary>
/// <param name="server">WebSocket server</param>
public WsSession(WsServer server) : base(server) { WebSocket = new WebSocket(this); }

// WebSocket connection methods
public virtual bool Close(int status) { SendCloseAsync(status, Span<byte>.Empty); base.Disconnect(); return true; }
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendCloseAsync(status, buffer); base.Disconnect(); return true; }

#region WebSocket send text methods

Expand Down
14 changes: 12 additions & 2 deletions source/NetCoreServer/WssClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,18 @@ public class WssClient : HttpsClient, IWebSocket

public override bool Connect() { _syncConnect = true; return base.Connect(); }
public override bool ConnectAsync() { _syncConnect = false; return base.ConnectAsync(); }
public virtual bool Close(int status) { SendClose(status, Span<byte>.Empty); base.Disconnect(); return true; }
public virtual bool CloseAsync(int status) { SendCloseAsync(status, Span<byte>.Empty); base.DisconnectAsync(); return true; }
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.Disconnect(); return true; }
public virtual bool CloseAsync(int status) => CloseAsync(status, Span<byte>.Empty);
public virtual bool CloseAsync(int status, string text) => CloseAsync(status, Encoding.UTF8.GetBytes(text));
public virtual bool CloseAsync(int status, ReadOnlySpan<char> text) => CloseAsync(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool CloseAsync(int status, byte[] buffer) => CloseAsync(status, buffer.AsSpan());
public virtual bool CloseAsync(int status, byte[] buffer, long offset, long size) => CloseAsync(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool CloseAsync(int status, ReadOnlySpan<byte> buffer) { SendClose(status, buffer); base.DisconnectAsync(); return true; }

#endregion

Expand Down
9 changes: 7 additions & 2 deletions source/NetCoreServer/WssServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ public class WssServer : HttpsServer, IWebSocket

#region Session management

public virtual bool CloseAll(int status)
public virtual bool CloseAll(int status) => CloseAll(status, Span<byte>.Empty);
public virtual bool CloseAll(int status, string text) => CloseAll(status, Encoding.UTF8.GetBytes(text));
public virtual bool CloseAll(int status, ReadOnlySpan<char> text) => CloseAll(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool CloseAll(int status, byte[] buffer) => CloseAll(status, buffer.AsSpan());
public virtual bool CloseAll(int status, byte[] buffer, long offset, long size) => CloseAll(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool CloseAll(int status, ReadOnlySpan<byte> buffer)
{
lock (WebSocket.WsSendLock)
{
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, Span<byte>.Empty, status);
WebSocket.PrepareSendFrame(WebSocket.WS_FIN | WebSocket.WS_CLOSE, false, buffer, status);
if (!Multicast(WebSocket.WsSendBuffer.AsSpan()))
return false;

Expand Down
11 changes: 10 additions & 1 deletion source/NetCoreServer/WssSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,19 @@ public class WssSession : HttpsSession, IWebSocket
{
internal readonly WebSocket WebSocket;

/// <summary>
/// Initialize a new WebSocket session
/// </summary>
/// <param name="server">WebSocket server</param>
public WssSession(WssServer server) : base(server) { WebSocket = new WebSocket(this); }

// WebSocket connection methods
public virtual bool Close(int status) { SendCloseAsync(status, Span<byte>.Empty); base.Disconnect(); return true; }
public virtual bool Close(int status) => Close(status, Span<byte>.Empty);
public virtual bool Close(int status, string text) => Close(status, Encoding.UTF8.GetBytes(text));
public virtual bool Close(int status, ReadOnlySpan<char> text) => Close(status, Encoding.UTF8.GetBytes(text.ToArray()));
public virtual bool Close(int status, byte[] buffer) => Close(status, buffer.AsSpan());
public virtual bool Close(int status, byte[] buffer, long offset, long size) => Close(status, buffer.AsSpan((int)offset, (int)size));
public virtual bool Close(int status, ReadOnlySpan<byte> buffer) { SendCloseAsync(status, buffer); base.Disconnect(); return true; }

#region WebSocket send text methods

Expand Down

0 comments on commit 6c4ba9e

Please sign in to comment.