123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- using Microsoft.AspNetCore.Http;
- using Microsoft.Extensions.Logging;
- using System.Net;
- using System.Net.WebSockets;
- using System.Text;
- namespace EVCB_OCPP.WSServer.Service.WsService;
- public class WsSession
- {
- public WsSession(ILogger<WsSession> logger)
- {
- this.logger = logger;
- }
- public PathString? Path { get; set; }
- public string UriScheme { get; set; }
- public string SessionID { get; set; }
- public IPEndPoint Endpoint { 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 CancellationToken DisconnetCancellationToken => disconnectCancellationTokenSource.Token;
- //public event OCPPClientDataEventHandler<WsSession, String> m_ReceiveData;
- public event EventHandler<string> SessionClosed;
- private CancellationTokenSource disconnectCancellationTokenSource = new CancellationTokenSource();
- private Task ReceiveLoopTask;
- private readonly ILogger<WsSession> logger;
- private void Init(WebSocket webSocket)
- {
- _WebSocket = webSocket;
- LastActiveTime = DateTime.UtcNow;
- ReceiveLoopTask = StartReceivd(webSocket, disconnectCancellationTokenSource.Token);
- }
- private async Task StartReceivd(WebSocket webSocket, CancellationToken token)
- {
- logger.LogInformation("{id} {func} {Path} Start", SessionID, nameof(StartReceivd), Path);
- byte[] prevBuffer = new byte[0];
- byte[] receivdBuffer = new byte[0];
- int bufferExpand = 1;
- int receivedBytes = 0;
- while (!token.IsCancellationRequested)
- {
- var tempReceiveBuffer = new byte[1024 * 4];
- WebSocketReceiveResult result = null;
- try
- {
- result = await webSocket.ReceiveAsync(new ArraySegment<byte>(tempReceiveBuffer), token);
- }
- catch (Exception e)
- {
- _ = BruteClose(e.Message);
- break;
- }
- LastActiveTime = DateTime.UtcNow;
- if (result == null || result.CloseStatus.HasValue)
- {
- //closed gracefully
- await GracefulClose(result.CloseStatus.Value);
- break;
- }
- prevBuffer = receivdBuffer;
- receivdBuffer = new byte[1024 * 4 * bufferExpand];
- Array.Copy(prevBuffer, 0, receivdBuffer, 0, receivedBytes);
- Array.Copy(tempReceiveBuffer, 0, receivdBuffer, receivedBytes, result.Count);
- receivedBytes += result.Count;
- if (!result.EndOfMessage)
- {
- bufferExpand++;
- continue;
- }
- var received = Encoding.UTF8.GetString(receivdBuffer, 0, receivedBytes);
- //logger.LogInformation("{func}:{Path} {value}", nameof(StartReceivd), Path, received);
- HandleReceivedData(received);
- bufferExpand = 1;
- receivedBytes = 0;
- }
- }
- internal virtual void HandleReceivedData(string data)
- {
- }
- internal Task Send(string dataString)
- {
- //logger.LogInformation("{func}:{Path} {value}", nameof(Send), Path, dataString);
- var data = Encoding.UTF8.GetBytes(dataString);
- return Send(data);
- }
- internal Task Close()
- {
- return ServerClose();
- }
- private async Task Send(byte[] data)
- {
- try
- {
- await ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: disconnectCancellationTokenSource.Token);
- }
- catch (Exception e)
- {
- logger.LogInformation("{func} {Path} exception:{msg}", nameof(Send), Path, e.Message);
- }
- }
- private Task ServerClose()
- {
- //logger.LogInformation("{func}:{Path}", nameof(ServerClose), Path);
- SessionClosed?.Invoke(this, "ServerShutdown");
- return InternalClose(WebSocketCloseStatus.NormalClosure, "ServerShutdown");
- }
- private Task GracefulClose(WebSocketCloseStatus closeStatus)
- {
- //logger.LogInformation("{func}:{Path} {value}", nameof(GracefulClose), Path, closeStatus);
- SessionClosed?.Invoke(this, closeStatus.ToString());
- return InternalClose(closeStatus, null);
- }
- private Task BruteClose(string description)
- {
- //logger.LogInformation("{func}:{Path} {value}", nameof(ServerClose), Path, description);
- SessionClosed?.Invoke(this, description);
- return InternalClose(WebSocketCloseStatus.EndpointUnavailable, description);
- }
- private async Task InternalClose(WebSocketCloseStatus closeStatus, string description)
- {
- try
- {
- await _WebSocket.CloseAsync(closeStatus, description, default);
- }
- catch
- {
- }
- finally
- {
- _WebSocket.Dispose();
- }
- disconnectCancellationTokenSource.Cancel();
- EndConnSemaphore.Release();
- }
- }
|