PluralRichPresence/PluralRichPresnce/Api/AWebSocket.cs

137 lines
4.0 KiB
C#

using Newtonsoft.Json;
using PluralRichPresence.Api;
using System.Dynamic;
using System.Net.WebSockets;
using System.Text;
namespace PluralRichPresence.Api
{
public class AWebSocket : IDisposable
{
private string websocketServerUri;
SemaphoreSlim? semaphore = new SemaphoreSlim(1, 1);
ClientWebSocket? wss = null;
public event EventHandler<DataReceivedEventArgs>? DataReceived;
public event EventHandler<TextReceivedEventArgs>? TextReceived;
public event EventHandler? Disconnected;
private void onTextReceived(string receivedString)
{
if (TextReceived is not null)
{
TextReceived(this, new TextReceivedEventArgs(receivedString));
}
}
private void onDataReceived(byte[] receivedData)
{
if (DataReceived is not null)
{
DataReceived(this, new DataReceivedEventArgs(receivedData));
}
}
private void onDisconnect()
{
if (Disconnected is not null)
{
if (semaphore is null || !semaphore.Wait(0)) return;
Disconnected(this, new EventArgs());
}
}
public AWebSocket(string serverUri)
{
this.websocketServerUri = serverUri;
}
private async Task<string> receiveMessageText()
{
byte[] byteArray = await receiveMessageBytes();
return Encoding.UTF8.GetString(byteArray);
}
private async Task<byte[]> receiveMessageBytes()
{
List<byte> totalPayload = new List<byte>();
byte[] buffer = new byte[0x8000];
while (wss is not null && wss.State == WebSocketState.Open)
{
try
{
WebSocketReceiveResult? result = await wss.ReceiveAsync(buffer, CancellationToken.None);
for (int i = 0; i < result.Count; i++)
totalPayload.Add(buffer[i]);
if (result.EndOfMessage)
return totalPayload.ToArray();
}
catch(Exception) { onDisconnect(); break; };
}
return totalPayload.ToArray();
}
private async Task receiveTask()
{
while (wss is not null && wss.State == WebSocketState.Open) {
try {
string message = await receiveMessageText();
Logger.Debug("< " + message);
onTextReceived(message);
}
catch (Exception) { Logger.Debug("failed"); break; };
}
onDisconnect();
}
public async Task Connect()
{
wss = new ClientWebSocket();
await wss.ConnectAsync(new Uri(this.websocketServerUri), CancellationToken.None);
_ = Task.Run(() => receiveTask());
try {
if(semaphore is not null)
semaphore.Release();
}
catch (SemaphoreFullException) { };
}
public async Task SendText(string text)
{
Logger.Debug("> "+text);
try {
if (wss is not null)
await wss.SendAsync(Encoding.UTF8.GetBytes(text), WebSocketMessageType.Text, true, CancellationToken.None);
}
catch (Exception) { onDisconnect(); }
}
public async Task Close()
{
if (wss is not null)
await wss.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None);
}
public void Dispose()
{
if(wss is not null)
{
this.Close().Wait();
wss.Dispose();
wss = null;
}
if (semaphore is not null)
{
semaphore.Dispose();
semaphore = null;
}
}
}
}