2024-04-07 17:17:11 +02:00
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Net.WebSockets;
|
|
|
|
|
2024-04-10 19:25:45 +02:00
|
|
|
namespace TanksServer.Interactivity;
|
2024-04-07 17:17:11 +02:00
|
|
|
|
2024-04-13 12:33:08 +02:00
|
|
|
internal sealed class ByteChannelWebSocket(WebSocket socket, ILogger logger, int messageSize)
|
2024-04-07 17:17:11 +02:00
|
|
|
{
|
2024-04-13 12:33:08 +02:00
|
|
|
private readonly byte[] _buffer = new byte[messageSize];
|
2024-04-07 17:17:11 +02:00
|
|
|
|
2024-04-15 20:34:23 +02:00
|
|
|
public ValueTask SendAsync(ReadOnlyMemory<byte> data, bool endOfMessage = true) =>
|
|
|
|
socket.SendAsync(data, WebSocketMessageType.Binary, endOfMessage, CancellationToken.None);
|
2024-04-07 17:17:11 +02:00
|
|
|
|
2024-04-13 12:33:08 +02:00
|
|
|
public async IAsyncEnumerable<Memory<byte>> ReadAllAsync()
|
2024-04-07 17:17:11 +02:00
|
|
|
{
|
2024-04-13 14:07:14 +02:00
|
|
|
while (socket.State is WebSocketState.Open or WebSocketState.CloseSent)
|
2024-04-07 17:17:11 +02:00
|
|
|
{
|
2024-04-13 14:07:14 +02:00
|
|
|
if (await TryReadAsync())
|
|
|
|
yield return _buffer.ToArray();
|
|
|
|
}
|
|
|
|
|
2024-04-13 16:27:45 +02:00
|
|
|
if (socket.State is not WebSocketState.Closed and not WebSocketState.Aborted)
|
2024-04-13 14:07:14 +02:00
|
|
|
Debugger.Break();
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task CloseAsync()
|
|
|
|
{
|
|
|
|
if (socket.State != WebSocketState.Open)
|
|
|
|
return;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
|
|
|
|
}
|
|
|
|
catch (WebSocketException socketException)
|
|
|
|
{
|
|
|
|
logger.LogDebug(socketException, "could not close socket properly");
|
|
|
|
}
|
|
|
|
}
|
2024-04-07 17:17:11 +02:00
|
|
|
|
2024-04-13 14:07:14 +02:00
|
|
|
private async Task<bool> TryReadAsync()
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2024-04-13 12:33:08 +02:00
|
|
|
var response = await socket.ReceiveAsync(_buffer, CancellationToken.None);
|
2024-04-07 17:17:11 +02:00
|
|
|
if (response.MessageType == WebSocketMessageType.Close)
|
|
|
|
{
|
2024-04-13 14:07:14 +02:00
|
|
|
await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
|
|
|
|
CancellationToken.None);
|
|
|
|
return false;
|
2024-04-07 17:17:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (response.Count != _buffer.Length)
|
|
|
|
{
|
2024-04-13 14:07:14 +02:00
|
|
|
await socket.CloseOutputAsync(WebSocketCloseStatus.InvalidPayloadData,
|
2024-04-07 17:17:11 +02:00
|
|
|
"response has unexpected size",
|
|
|
|
CancellationToken.None);
|
2024-04-13 14:07:14 +02:00
|
|
|
return false;
|
2024-04-07 17:17:11 +02:00
|
|
|
}
|
|
|
|
|
2024-04-13 14:07:14 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
catch (WebSocketException socketException)
|
|
|
|
{
|
|
|
|
logger.LogDebug(socketException, "could not read");
|
|
|
|
return false;
|
2024-04-07 17:17:11 +02:00
|
|
|
}
|
|
|
|
}
|
2024-04-13 14:07:14 +02:00
|
|
|
}
|