This repository has been archived on 2023-10-16. You can view files and clone it, but cannot push or open issues or pull requests.
hamakaze/Hamakaze/WebSocket/WsClient.cs

139 lines
3.8 KiB
C#

using System;
using System.Threading;
namespace Hamakaze.WebSocket {
public class WsClient : IDisposable {
public WsConnection Connection { get; }
public bool IsRunning { get; private set; } = true;
private Thread ReadThread { get; }
private Action<WsMessage> MessageHandler { get; }
private Action<Exception> ExceptionHandler { get; }
private Mutex SendLock { get; }
public WsClient(
WsConnection connection,
Action<WsMessage> messageHandler,
Action<Exception> exceptionHandler
) {
Connection = connection ?? throw new ArgumentNullException(nameof(connection));
MessageHandler = messageHandler ?? throw new ArgumentNullException(nameof(messageHandler));
ExceptionHandler = exceptionHandler ?? throw new ArgumentNullException(nameof(exceptionHandler));
SendLock = new();
ReadThread = new(ReadThreadBody) { IsBackground = true };
ReadThread.Start();
}
private void ReadThreadBody() {
try {
while(IsRunning)
MessageHandler(Connection.Receive());
} catch(Exception ex) {
IsRunning = false;
ExceptionHandler(ex);
}
}
public void Send(string text) {
Connection.Send(text);
}
public void Send(object obj) {
if(obj == null)
throw new ArgumentNullException(nameof(obj));
Connection.Send(obj.ToString());
}
public void Send(ReadOnlySpan<byte> data) {
Connection.Send(data);
}
public void Send(byte[] buffer, int offset, int count) {
if(buffer == null)
throw new ArgumentNullException(nameof(buffer));
Connection.Send(buffer.AsSpan(offset, count));
}
public void Ping() {
Connection.Ping();
}
public void Ping(ReadOnlySpan<byte> data) {
Connection.Ping(data);
}
public void Ping(byte[] buffer, int offset, int length) {
if(buffer == null)
throw new ArgumentNullException(nameof(buffer));
Connection.Ping(buffer.AsSpan(offset, length));
}
public void Pong() {
Connection.Pong();
}
public void Pong(ReadOnlySpan<byte> data) {
Connection.Pong(data);
}
public void Pong(byte[] buffer, int offset, int length) {
if(buffer == null)
throw new ArgumentNullException(nameof(buffer));
Pong(buffer.AsSpan(offset, length));
}
public void Close() {
Connection.Close(WsCloseReason.NormalClosure);
}
public void CloseEmpty() {
Connection.CloseEmpty();
}
public void Close(string reason) {
Connection.Close(WsCloseReason.NormalClosure, reason);
}
public void Close(byte[] buffer, int offset, int length) {
if(buffer == null)
throw new ArgumentNullException(nameof(buffer));
Connection.Close(buffer.AsSpan(offset, length));
}
public void Close(WsCloseReason code, byte[] buffer, int offset, int length) {
if(buffer == null)
throw new ArgumentNullException(nameof(buffer));
Connection.Close(code, buffer.AsSpan(offset, length));
}
private bool IsDisposed;
~WsClient() {
DoDispose();
}
public void Dispose() {
DoDispose();
GC.SuppressFinalize(this);
}
private void DoDispose() {
if(IsDisposed)
return;
IsDisposed = true;
SendLock.Dispose();
Connection.Dispose();
}
}
}