mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 17:58:26 -04:00
Killed history
This commit is contained in:
154
src/ayu/Ayu.Discord.Voice/SocketClient.cs
Normal file
154
src/ayu/Ayu.Discord.Voice/SocketClient.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
using Serilog;
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Ayu.Discord.Voice;
|
||||
|
||||
namespace Ayu.Discord.Gateway
|
||||
{
|
||||
public class SocketClient : IDisposable
|
||||
{
|
||||
private ClientWebSocket? _ws = null;
|
||||
|
||||
public event Func<byte[], Task>? PayloadReceived = delegate { return Task.CompletedTask; };
|
||||
public event Func<string, Task>? WebsocketClosed = delegate { return Task.CompletedTask; };
|
||||
|
||||
const int CHUNK_SIZE = 1024 * 16;
|
||||
|
||||
public async Task RunAndBlockAsync(Uri url, CancellationToken cancel)
|
||||
{
|
||||
var error = "Error.";
|
||||
var bufferWriter = new ArrayBufferWriter<byte>(CHUNK_SIZE);
|
||||
try
|
||||
{
|
||||
using (_ws = new ClientWebSocket())
|
||||
{
|
||||
await _ws.ConnectAsync(url, cancel).ConfigureAwait(false);
|
||||
// WebsocketConnected!.Invoke(this);
|
||||
|
||||
while (true)
|
||||
{
|
||||
var result = await _ws.ReceiveAsync(bufferWriter.GetMemory(CHUNK_SIZE), cancel);
|
||||
bufferWriter.Advance(result.Count);
|
||||
if (result.MessageType == WebSocketMessageType.Close)
|
||||
{
|
||||
var closeMessage = CloseCodes.GetErrorCodeMessage((int?) _ws.CloseStatus ?? 0).Message;
|
||||
error = $"Websocket closed ({_ws.CloseStatus}): {_ws.CloseStatusDescription} {closeMessage}";
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.EndOfMessage)
|
||||
{
|
||||
var pr = PayloadReceived;
|
||||
var data = bufferWriter.WrittenMemory.ToArray();
|
||||
bufferWriter.Clear();
|
||||
|
||||
if (!(pr is null))
|
||||
{
|
||||
await pr.Invoke(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (WebSocketException ex)
|
||||
{
|
||||
Log.Warning("Disconnected, check your internet connection...");
|
||||
Log.Debug(ex, "Websocket Exception in websocket client");
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error in websocket client. {Message}", ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
bufferWriter.Clear();
|
||||
_ws = null;
|
||||
await ClosedAsync(error).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ClosedAsync(string msg = "Error")
|
||||
{
|
||||
try
|
||||
{
|
||||
await WebsocketClosed!.Invoke(msg).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private readonly SemaphoreSlim _sendLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
public async Task SendAsync(byte[] data)
|
||||
{
|
||||
await _sendLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
var ws = _ws;
|
||||
if (ws is null)
|
||||
throw new WebSocketException("Websocket is disconnected.");
|
||||
for (int i = 0; i < data.Length; i += 4096)
|
||||
{
|
||||
var count = i + 4096 > data.Length ? data.Length - i : 4096;
|
||||
await ws.SendAsync(new ArraySegment<byte>(data, i, count),
|
||||
WebSocketMessageType.Text,
|
||||
i + count >= data.Length,
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_sendLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendBulkAsync(byte[] data)
|
||||
{
|
||||
var ws = _ws;
|
||||
if (ws is null)
|
||||
throw new WebSocketException("Websocket is disconnected.");
|
||||
|
||||
await ws.SendAsync(new ArraySegment<byte>(data, 0, data.Length),
|
||||
WebSocketMessageType.Binary,
|
||||
true,
|
||||
CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<bool> CloseAsync(string msg = "Stop")
|
||||
{
|
||||
if (_ws != null && _ws.State != WebSocketState.Closed)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _ws.CloseAsync(WebSocketCloseStatus.InternalServerError, msg, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
PayloadReceived = null;
|
||||
WebsocketClosed = null;
|
||||
var ws = _ws;
|
||||
if (ws is null)
|
||||
return;
|
||||
|
||||
ws.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user