WebsocketService.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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 event EventHandler<T> SessionClosed;
  56. public async Task AddWebSocket(WebSocket webSocket, HttpContext context)
  57. {
  58. T data = Activator.CreateInstance<T>();
  59. data.ClientWebSocket = webSocket;
  60. data.Path = context?.Request?.Path;
  61. data.UriScheme = context?.Request?.Scheme;
  62. data.AuthHeader = context?.Request?.Headers?.Authorization;
  63. data.SessionID = context.Session.Id;
  64. data.Endpoint = context.GetEndpoint();
  65. data.Origin = context.Request.Headers.Origin;
  66. var validated = await ValidateHandshake(data);
  67. if (!validated)
  68. {
  69. return;
  70. }
  71. NewSessionConnected?.Invoke(this, data);
  72. await data.EndConnSemaphore.WaitAsync();
  73. return;
  74. }
  75. }
  76. public class WsSession
  77. {
  78. public WsSession()
  79. {
  80. }
  81. public PathString? Path { get; set; }
  82. public string UriScheme { get; set; }
  83. public string AuthHeader { get; set; }
  84. public string SessionID { get; set; }
  85. public Endpoint Endpoint { get; internal set; }
  86. public StringValues Origin { get; internal 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. ReceiveLoopTask = StartReceivd(webSocket);
  104. }
  105. private async Task StartReceivd(WebSocket webSocket)
  106. {
  107. while (true)
  108. {
  109. var buffer = new byte[1024 * 4];
  110. var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), default);
  111. if (result.CloseStatus.HasValue)
  112. {
  113. Close(CloseReason.ClientClosing);
  114. break;
  115. }
  116. string received = Encoding.UTF8.GetString(buffer, 0, result.Count);
  117. m_ReceiveData?.Invoke(this, received);
  118. }
  119. }
  120. internal void Send(string dataString)
  121. {
  122. var data = Encoding.UTF8.GetBytes(dataString);
  123. ClientWebSocket.SendAsync(data, WebSocketMessageType.Binary, endOfMessage: true, cancellationToken: default);
  124. }
  125. internal void Send(byte[] data, int offset, int length)
  126. {
  127. ClientWebSocket.SendAsync(data, WebSocketMessageType.Binary, endOfMessage: true, cancellationToken: default);
  128. }
  129. internal void Close(CloseReason closeReason)
  130. {
  131. SessionClosed?.Invoke(this, null);
  132. _WebSocket.Dispose();
  133. EndConnSemaphore.Release();
  134. }
  135. }