using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Server_Dashboard_Socket {
///
/// Generic Channel class that handles the connection and message sending / receiving
/// Inherits IDisposable to correctly cut the connection to the server
///
/// The Protocol type, either JsonMessageProtocol or XmlMessageProtocol
/// The message type, either JObject or XDocument
public abstract class SocketChannel : IDisposable
where TProtocol : Protocol, new() {
protected bool isDisposable = false;
private NetworkStream networkStream;
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly TProtocol protocol = new TProtocol();
private Func messageCallback;
///
/// Attaches the socket to a network stream that owns the socket
/// if the network stream goes down it takes the socket with it!
///
/// A Socket
public void Attach(Socket socket) {
networkStream = new NetworkStream(socket, true);
_ = Task.Run(ReceiveLoop, cancellationTokenSource.Token);
}
///
/// Takes a function with a message and sets the private member to the functions value
///
///
public void OnMessage(Func callbackHandler) => messageCallback = callbackHandler;
///
/// Makes sure to close the socket
///
public void Close() {
cancellationTokenSource.Cancel();
networkStream?.Close();
}
///
/// Sends the message async
///
/// Anything as message, e.g. object or string
/// The message
///
public async Task SendAsync(T message) => await protocol.SendAsync(networkStream, message).ConfigureAwait(false);
///
/// Checks for received messages
///
/// received message
protected virtual async Task ReceiveLoop() {
while (!cancellationTokenSource.Token.IsCancellationRequested) {
var msg = await protocol.ReceiveAsync(networkStream).ConfigureAwait(false);
await messageCallback(msg).ConfigureAwait(false);
}
}
///
/// Deconstructor sets Dispose to false
///
~SocketChannel() => Dispose(false);
///
/// Sets dispose to true
///
public void Dispose() => Dispose(true);
///
/// Disposes open sockets
///
/// Is it currently disposing stuff?
protected void Dispose(bool isDisposing) {
//If its not disposable
if (!isDisposable) {
//Set disposable to true
isDisposable = true;
//Close the socket
Close();
//If its closed, dispose it
networkStream?.Dispose();
//Wait with the garbage collection until the disposing is done
if (isDisposing)
GC.SuppressFinalize(this);
}
}
}
}