WebsocketService.cs 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. using Microsoft.AspNetCore.Builder;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using Microsoft.Extensions.Primitives;
  5. using OCPPServer.Protocol;
  6. using SuperSocket.SocketBase;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Net.WebSockets;
  11. using System.ServiceModel.Channels;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using static OCPPServer.Protocol.ClientData;
  15. namespace EVCB_OCPP.WSServer.Service;
  16. public static class AppExtention
  17. {
  18. public static void MapWsService(this WebApplication webApplication)
  19. {
  20. var protocals = new List<string>() { "", "ocpp1.6", "ocpp2.0" };
  21. webApplication.UseWebSockets(new WebSocketOptions()
  22. {
  23. KeepAliveInterval = TimeSpan.FromSeconds(10)
  24. });
  25. webApplication.Use(async (HttpContext context, RequestDelegate next) => {
  26. if (context.WebSockets.IsWebSocketRequest)
  27. {
  28. var matched = context.WebSockets.WebSocketRequestedProtocols.Intersect(protocals);
  29. if (matched is null || !matched.Any())
  30. {
  31. await context.Response.WriteAsync("Protocol not matched");
  32. return;
  33. }
  34. using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(matched.First());
  35. var servcie = context.RequestServices.GetService<WebsocketService<WsClientData>>();
  36. await servcie.AddWebSocket(webSocket, context);
  37. return;
  38. }
  39. else
  40. {
  41. await next(context);
  42. }
  43. });
  44. }
  45. }
  46. public interface IWebsocketService
  47. {
  48. public Task AddWebSocket(WebSocket webSocket, HttpContext context);
  49. }
  50. public class WebsocketService<T> : IWebsocketService where T: WsSession
  51. {
  52. public WebsocketService() { }
  53. public Func<T, Task<bool>> ValidateHandshake;
  54. public event EventHandler<T> NewSessionConnected;
  55. public async Task AddWebSocket(WebSocket webSocket, HttpContext context)
  56. {
  57. T data = Activator.CreateInstance<T>();
  58. data.ClientWebSocket = webSocket;
  59. data.Path = context?.Request?.Path;
  60. data.UriScheme = context?.Request?.Scheme;
  61. data.AuthHeader = context?.Request?.Headers?.Authorization;
  62. data.SessionID = context.TraceIdentifier;
  63. data.Endpoint = null;
  64. data.Origin = context.Request.Headers.Origin;
  65. var validated = await ValidateHandshake(data);
  66. if (!validated)
  67. {
  68. return;
  69. }
  70. NewSessionConnected?.Invoke(this, data);
  71. await data.EndConnSemaphore.WaitAsync();
  72. return;
  73. }
  74. }
  75. public class WsSession
  76. {
  77. public WsSession()
  78. {
  79. }
  80. public PathString? Path { get; set; }
  81. public string UriScheme { get; set; }
  82. public string AuthHeader { get; set; }
  83. public string SessionID { get; set; }
  84. public Endpoint Endpoint { get; internal set; }
  85. public StringValues Origin { get; internal set; }
  86. public DateTime LastActiveTime { get; set; }
  87. public WebSocket _WebSocket { get; internal set; }
  88. public WebSocket ClientWebSocket {
  89. get => _WebSocket;
  90. set
  91. {
  92. Init(value);
  93. }
  94. }
  95. public WebSocketState State => ClientWebSocket.State;
  96. public string SecWebSocketProtocol => ClientWebSocket.SubProtocol;
  97. public SemaphoreSlim EndConnSemaphore { get; } = new SemaphoreSlim(0);
  98. //public event OCPPClientDataEventHandler<WsSession, String> m_ReceiveData;
  99. public event EventHandler SessionClosed;
  100. private Task ReceiveLoopTask;
  101. private void Init(WebSocket webSocket)
  102. {
  103. _WebSocket = webSocket;
  104. ReceiveLoopTask = StartReceivd(webSocket);
  105. }
  106. private async Task StartReceivd(WebSocket webSocket)
  107. {
  108. while (true)
  109. {
  110. var buffer = new byte[1024 * 4];
  111. var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), default);
  112. if (result.CloseStatus.HasValue)
  113. {
  114. Close(CloseReason.ClientClosing);
  115. break;
  116. }
  117. string received = Encoding.UTF8.GetString(buffer, 0, result.Count);
  118. //m_ReceiveData?.Invoke(this, received);
  119. this.LastActiveTime = DateTime.UtcNow;
  120. HandleReceivedData(received);
  121. }
  122. }
  123. internal virtual void HandleReceivedData(string data)
  124. {
  125. }
  126. internal void Send(string dataString)
  127. {
  128. var data = Encoding.UTF8.GetBytes(dataString);
  129. ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: default);
  130. }
  131. internal void Send(byte[] data, int offset, int length)
  132. {
  133. ClientWebSocket.SendAsync(data, WebSocketMessageType.Text, endOfMessage: true, cancellationToken: default);
  134. }
  135. internal void Close(CloseReason closeReason)
  136. {
  137. SessionClosed?.Invoke(this, null);
  138. _WebSocket.Dispose();
  139. EndConnSemaphore.Release();
  140. }
  141. }