using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Primitives; using System; using System.Collections.Generic; using System.Linq; using System.Net.WebSockets; using System.Text; using System.Threading.Tasks; namespace EVCB_OCPP.WSServer.Service.WsService { public class WsSession { public WsSession() { } public PathString? Path { get; set; } public string UriScheme { get; set; } public string AuthHeader { get; set; } public string SessionID { get; set; } public Endpoint Endpoint { get; internal set; } public StringValues Origin { get; internal set; } public DateTime LastActiveTime { get; set; } private WebSocket _WebSocket; public WebSocket ClientWebSocket { get => _WebSocket; set { Init(value); } } public WebSocketState State => ClientWebSocket.State; public string SecWebSocketProtocol => ClientWebSocket.SubProtocol; public SemaphoreSlim EndConnSemaphore { get; } = new SemaphoreSlim(0); //public event OCPPClientDataEventHandler m_ReceiveData; public event EventHandler SessionClosed; private CancellationTokenSource disconnectCancellationTokenSource = new CancellationTokenSource(); private Task ReceiveLoopTask; private void Init(WebSocket webSocket) { _WebSocket = webSocket; ReceiveLoopTask = StartReceivd(webSocket, disconnectCancellationTokenSource.Token); } private async Task StartReceivd(WebSocket webSocket, CancellationToken token) { while (!token.IsCancellationRequested) { var buffer = new byte[1024 * 4]; var result = await webSocket.ReceiveAsync(new ArraySegment(buffer), token); if (result.CloseStatus.HasValue) { _ = Close(CloseReason.ClientClosing); break; } string received = Encoding.UTF8.GetString(buffer, 0, result.Count); //m_ReceiveData?.Invoke(this, received); LastActiveTime = DateTime.UtcNow; HandleReceivedData(received); } } internal virtual void HandleReceivedData(string data) { } internal void Send(string dataString) { var data = Encoding.UTF8.GetBytes(dataString); ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token); } internal void Send(byte[] data, int offset, int length) { ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token); } internal async Task Close(CloseReason closeReason) { try { await _WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, closeReason.ToString(), default); } finally { _WebSocket.Dispose(); } disconnectCancellationTokenSource.Cancel(); SessionClosed?.Invoke(this, closeReason); EndConnSemaphore.Release(); } } }