123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- using Microsoft.AspNetCore.Builder;
- using Microsoft.AspNetCore.Http;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Primitives;
- using OCPPServer.Protocol;
- using SuperSocket.SocketBase;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.WebSockets;
- using System.ServiceModel.Channels;
- using System.Text;
- using System.Threading.Tasks;
- using static OCPPServer.Protocol.ClientData;
- namespace EVCB_OCPP.WSServer.Service;
- public static class AppExtention
- {
- public static void MapWsService(this WebApplication webApplication)
- {
- var protocals = new List<string>() { "", "ocpp1.6", "ocpp2.0" };
- webApplication.UseWebSockets(new WebSocketOptions()
- {
- KeepAliveInterval = TimeSpan.FromSeconds(10)
- });
- webApplication.Use(async (HttpContext context, RequestDelegate next) => {
- if (context.WebSockets.IsWebSocketRequest)
- {
- var matched = context.WebSockets.WebSocketRequestedProtocols.Intersect(protocals);
- if (matched is null || !matched.Any())
- {
- await context.Response.WriteAsync("Protocol not matched");
- return;
- }
- using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(matched.First());
- var servcie = context.RequestServices.GetService<WebsocketService<WsClientData>>();
- await servcie.AddWebSocket(webSocket, context);
- return;
- }
- else
- {
- await next(context);
- }
- });
- }
- }
- public interface IWebsocketService
- {
- public Task AddWebSocket(WebSocket webSocket, HttpContext context);
- }
- public class WebsocketService<T> : IWebsocketService where T: WsSession
- {
- public WebsocketService() { }
- public Func<T, Task<bool>> ValidateHandshake;
- public event EventHandler<T> NewSessionConnected;
- public event EventHandler<T> SessionClosed;
- public async Task AddWebSocket(WebSocket webSocket, HttpContext context)
- {
- T data = Activator.CreateInstance<T>();
- data.ClientWebSocket = webSocket;
- data.Path = context?.Request?.Path;
- data.UriScheme = context?.Request?.Scheme;
- data.AuthHeader = context?.Request?.Headers?.Authorization;
- data.SessionID = context.Session.Id;
- data.Endpoint = context.GetEndpoint();
- data.Origin = context.Request.Headers.Origin;
- var validated = await ValidateHandshake(data);
- if (!validated)
- {
- return;
- }
- NewSessionConnected?.Invoke(this, data);
- await data.EndConnSemaphore.WaitAsync();
- return;
- }
- }
- 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 WebSocket _WebSocket { get; internal set; }
- 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<WsSession, String> m_ReceiveData;
- public event EventHandler SessionClosed;
- private Task ReceiveLoopTask;
- private void Init(WebSocket webSocket)
- {
- ReceiveLoopTask = StartReceivd(webSocket);
- }
- private async Task StartReceivd(WebSocket webSocket)
- {
- while (true)
- {
- var buffer = new byte[1024 * 4];
- var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), default);
- if (result.CloseStatus.HasValue)
- {
- Close(CloseReason.ClientClosing);
- break;
- }
- string received = Encoding.UTF8.GetString(buffer, 0, result.Count);
- m_ReceiveData?.Invoke(this, received);
- }
- }
- internal void Send(string dataString)
- {
- var data = Encoding.UTF8.GetBytes(dataString);
- ClientWebSocket.SendAsync(data, WebSocketMessageType.Binary, endOfMessage: true, cancellationToken: default);
- }
- internal void Send(byte[] data, int offset, int length)
- {
- ClientWebSocket.SendAsync(data, WebSocketMessageType.Binary, endOfMessage: true, cancellationToken: default);
- }
- internal void Close(CloseReason closeReason)
- {
- SessionClosed?.Invoke(this, null);
- _WebSocket.Dispose();
- EndConnSemaphore.Release();
- }
- }
|