WebsocketService.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using Microsoft.AspNetCore.Builder;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using Microsoft.Extensions.Primitives;
  5. using System.Net;
  6. using System.Net.WebSockets;
  7. using System.Text;
  8. namespace EVCB_OCPP.WSServer.Service.WsService;
  9. public static class AppExtention
  10. {
  11. public static void MapWsService(this WebApplication webApplication)
  12. {
  13. var protocals = new List<string>() { "", "ocpp1.6", "ocpp2.0" };
  14. webApplication.UseWebSockets(new WebSocketOptions()
  15. {
  16. KeepAliveInterval = TimeSpan.FromSeconds(10)
  17. });
  18. webApplication.Use(async (context, next) =>
  19. {
  20. if (!context.WebSockets.IsWebSocketRequest)
  21. {
  22. await next(context);
  23. return;
  24. }
  25. var matched = context.WebSockets.WebSocketRequestedProtocols.Intersect(protocals);
  26. if (matched is null || !matched.Any())
  27. {
  28. await context.Response.WriteAsync("Protocol not matched");
  29. return;
  30. }
  31. using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(matched.Last());
  32. var servcie = context.RequestServices.GetService<WebsocketService<WsClientData>>();
  33. await servcie.AddWebSocket(webSocket, context);
  34. return;
  35. });
  36. }
  37. }
  38. public class WebsocketService<T> where T : WsSession
  39. {
  40. public WebsocketService() { }
  41. public Func<T, Task<bool>> ValidateHandshake;
  42. public event EventHandler<T> NewSessionConnected;
  43. public async Task AddWebSocket(WebSocket webSocket, HttpContext context)
  44. {
  45. T data = Activator.CreateInstance<T>();
  46. data.ClientWebSocket = webSocket;
  47. data.Path = context?.Request?.Path;
  48. data.UriScheme = context?.Request?.Scheme;
  49. data.AuthHeader = context?.Request?.Headers?.Authorization;
  50. data.SessionID = context.TraceIdentifier;
  51. data.Origin = context.Request.Headers.Origin;
  52. try
  53. {
  54. var ipaddress = context.Connection.RemoteIpAddress;
  55. var port = context.Connection.RemotePort;
  56. data.Endpoint = new IPEndPoint(ipaddress, port);
  57. }
  58. catch
  59. {
  60. data.Endpoint = null;
  61. }
  62. var validated = ValidateHandshake == null ? false : await ValidateHandshake(data);
  63. if (!validated)
  64. {
  65. return;
  66. }
  67. NewSessionConnected?.Invoke(this, data);
  68. await data.EndConnSemaphore.WaitAsync();
  69. return;
  70. }
  71. }
  72. public enum CloseReason
  73. {
  74. ClientClosing,
  75. ServerShutdown
  76. }