137 lines
4.0 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|