using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using System.Net; using System.Net.Http; using System.Net.WebSockets; using System.ServiceModel.Channels; namespace EVCB_OCPP.WSServer.Service.WsService; public class WebsocketService where T : WsSession { public WebsocketService(IServiceProvider serviceProvider) { this.serviceProvider = serviceProvider; } private readonly IServiceProvider serviceProvider; public event EventHandler NewSessionConnected; public async Task AcceptWebSocket(HttpContext context) { if (!context.WebSockets.IsWebSocketRequest) { return; } var portocol = await ValidateSupportedPortocol(context); if (string.IsNullOrEmpty(portocol)) { return; } T data = GetSession(context); if (!await ValidateHandshake(context, data)) { return; } using WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(portocol); await AddWebSocket(webSocket, data); } internal virtual ValueTask ValidateHandshake(HttpContext context, T data) { return ValueTask.FromResult(true); } internal virtual ValueTask ValidateSupportedPortocol(HttpContext context) { return ValueTask.FromResult(string.Empty); } private async Task AddWebSocket(WebSocket webSocket, T data) { data.ClientWebSocket = webSocket; NewSessionConnected?.Invoke(this, data); await data.EndConnSemaphore.WaitAsync(); return; } private T GetSession(HttpContext context) { T data = serviceProvider.GetRequiredService(); data.Path = context?.Request?.Path; data.SessionID = context.TraceIdentifier; data.UriScheme = GetScheme(context); try { var ipaddress = context.Connection.RemoteIpAddress; var port = context.Connection.RemotePort; data.Endpoint = new IPEndPoint(ipaddress, port); } catch { data.Endpoint = null; } return data; } private string GetScheme(HttpContext context) { string toReturn = string.Empty; if (context.Request.Headers.ContainsKey("x-original-host")) { toReturn = new Uri(context.Request.Headers["x-original-host"]).Scheme; return toReturn; } var origin = context.Request.Headers.Origin.FirstOrDefault(); try { toReturn = new Uri(origin).Scheme; return toReturn; } catch { } return toReturn; } }