✨ Handler.

Signed-off-by: 秋雨落 <i@rain.cx>
This commit is contained in:
秋雨落
2023-09-13 11:25:34 +08:00
parent cb14d7ff74
commit c43b48398e
10 changed files with 114 additions and 63 deletions
@@ -0,0 +1,17 @@
using System.Net.WebSockets;
using CrystalConnector.Utilities;
namespace CrystalConnector.Connector;
public class WebSocketConnectionManager
{
internal static Dictionary<WebSocket, WebSocketConnectionInfo> Info { get; } = new();
public static void DisconnectAll()
{
foreach (var (webSocket, info) in Info)
{
webSocket.Disconnect();
}
}
}
+1
View File
@@ -31,4 +31,5 @@
</None> </None>
</ItemGroup> </ItemGroup>
</Project> </Project>
+3 -2
View File
@@ -1,4 +1,5 @@
using CrystalConnector.Utilities; using CrystalConnector.Connector;
using CrystalConnector.Utilities;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -29,7 +30,7 @@ public class CrystalService : IHostedService
private void OnStopping() private void OnStopping()
{ {
Logger.LogInformation("Stopping!"); Logger.LogInformation("Stopping!");
WebSocketExtension.DisconnectAll(); WebSocketConnectionManager.DisconnectAll();
} }
private void OnStopped() private void OnStopped()
+18 -24
View File
@@ -1,42 +1,36 @@
using System.Net; using System.Formats.Cbor;
using System.Net.WebSockets; using System.Net.WebSockets;
using CrystalConnector.Utilities; using CrystalConnector.Utilities;
using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace CrystalConnector.Handlers; namespace CrystalConnector.Handlers;
public class WebSocketHandler : IWebSocketHandler public class WebSocketHandler
{ {
private IConfiguration Config { get; }
private ILogger<WebSocketHandler> Logger { get; } private ILogger<WebSocketHandler> Logger { get; }
public WebSocketHandler(ILogger<WebSocketHandler> logger) public WebSocketHandler(IConfiguration config, ILogger<WebSocketHandler> logger)
{ {
Config = config;
Logger = logger; Logger = logger;
} }
public async void StartHandle(HttpContext context, WebSocket webSocket, TaskCompletionSource<WebSocketHandleResult> taskCompletionSource) public void Handle(WebSocket webSocket, CborReader reader)
{ {
var remoteEndPoint = new IPEndPoint(context.Connection.RemoteIpAddress!, context.Connection.RemotePort); // qyl27: we believe it is a tcp connection. var type = reader.ReadTextString();
var receiveCancellationTokenSource = new CancellationTokenSource(); if (type == "Authenticate")
webSocket.AddData(context.Connection.Id, remoteEndPoint, taskCompletionSource, receiveCancellationTokenSource); {
await Handle(webSocket, receiveCancellationTokenSource.Token); if (!webSocket.GetConnectionInfo().Authorized)
{
var secret = reader.ReadTextString();
if (secret == Config.GetValue<string>("Connector:Auth:Secret"))
{
webSocket.GetConnectionInfo().Authorized = true;
}
} }
private async Task Handle(WebSocket webSocket, CancellationToken cancellationToken)
{
var buffer = new byte[1024 * 4];
WebSocketReceiveResult receiveResult;
do
{
receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), cancellationToken);
} while (!cancellationToken.IsCancellationRequested && !receiveResult.CloseStatus.HasValue);
} }
public void Disconnect(WebSocket webSocket)
{
webSocket.RemoveData();
} }
} }
+3 -1
View File
@@ -2,6 +2,7 @@
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using CrystalConnector; using CrystalConnector;
using CrystalConnector.Handlers; using CrystalConnector.Handlers;
using CrystalConnector.WebSockets;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -92,5 +93,6 @@ void ConfigureLogging(ILoggingBuilder logging)
void ConfigureServices(IServiceCollection services) void ConfigureServices(IServiceCollection services)
{ {
services.AddSingleton<IWebSocketHandler, WebSocketHandler>(); services.AddSingleton<IWebSocketManager, WebSocketManager>();
services.AddSingleton<WebSocketHandler>();
} }
+5 -6
View File
@@ -1,5 +1,5 @@
using CrystalConnector.Handlers; using CrystalConnector.Utilities;
using CrystalConnector.Utilities; using CrystalConnector.WebSockets;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -12,7 +12,7 @@ public class Startup
private IConfiguration Config { get; } private IConfiguration Config { get; }
private ILogger<Startup> Logger { get; set; } private ILogger<Startup> Logger { get; set; }
private IWebSocketHandler WebSocketHandler { get; set; } private IWebSocketManager WebSocketManager { get; set; }
public Startup(IConfiguration config) public Startup(IConfiguration config)
{ {
@@ -24,7 +24,7 @@ public class Startup
var provider = services.BuildServiceProvider(); var provider = services.BuildServiceProvider();
Logger = provider.GetService<ILogger<Startup>>()!; Logger = provider.GetService<ILogger<Startup>>()!;
WebSocketHandler = provider.GetService<IWebSocketHandler>()!; WebSocketManager = provider.GetService<IWebSocketManager>()!;
} }
public void Configure(IApplicationBuilder app) public void Configure(IApplicationBuilder app)
@@ -39,8 +39,7 @@ public class Startup
Logger.LogInformation("Got WebSocket connection from {Ip}:{Port}", context.Connection.RemoteIpAddress?.ToString(), context.Connection.RemotePort); Logger.LogInformation("Got WebSocket connection from {Ip}:{Port}", context.Connection.RemoteIpAddress?.ToString(), context.Connection.RemotePort);
var taskCompletionSource = new TaskCompletionSource<WebSocketHandleResult>(); var taskCompletionSource = new TaskCompletionSource<WebSocketHandleResult>();
WebSocketHandler.StartHandle(context, websocket, taskCompletionSource); await WebSocketManager.StartHandle(context, websocket, taskCompletionSource);
await taskCompletionSource.Task;
} }
else else
{ {
@@ -3,7 +3,7 @@ using CrystalConnector.Connector;
namespace CrystalConnector.Utilities; namespace CrystalConnector.Utilities;
public class WebSocketData public class WebSocketConnectionInfo
{ {
public required string Id { get; set; } public required string Id { get; set; }
@@ -11,8 +11,6 @@ public class WebSocketData
public required TaskCompletionSource<WebSocketHandleResult> CompletionSource { get; set; } public required TaskCompletionSource<WebSocketHandleResult> CompletionSource { get; set; }
public required CancellationTokenSource ReceiveCancellationTokenSource { get; set; }
public bool Authorized { get; set; } = false; public bool Authorized { get; set; } = false;
public List<MessageChannel> RegisteredChannels { get; } = new(); public List<MessageChannel> RegisteredChannels { get; } = new();
@@ -1,44 +1,34 @@
using System.Net; using System.Net;
using System.Net.WebSockets; using System.Net.WebSockets;
using CrystalConnector.Connector;
namespace CrystalConnector.Utilities; namespace CrystalConnector.Utilities;
public static class WebSocketExtension public static class WebSocketExtension
{ {
private static Dictionary<WebSocket, WebSocketData> Data { get; } = new(); public static void AddConnectionInfo(this WebSocket webSocket, string id, IPEndPoint ip,
TaskCompletionSource<WebSocketHandleResult> taskCompletionSource)
public static void AddData(this WebSocket webSocket, string id, IPEndPoint ip,
TaskCompletionSource<WebSocketHandleResult> taskCompletionSource,
CancellationTokenSource receiveCancellationTokenSource)
{ {
Data.Add(webSocket, new WebSocketData WebSocketConnectionManager.Info.Add(webSocket, new WebSocketConnectionInfo
{ {
Id = id, Id = id,
IpEndPoint = ip, IpEndPoint = ip,
CompletionSource = taskCompletionSource, CompletionSource = taskCompletionSource,
ReceiveCancellationTokenSource = receiveCancellationTokenSource
}); });
} }
public static WebSocketData GetData(this WebSocket webSocket) public static WebSocketConnectionInfo GetConnectionInfo(this WebSocket webSocket)
{ {
return Data[webSocket]; return WebSocketConnectionManager.Info[webSocket];
} }
public static void RemoveData(this WebSocket webSocket) public static void Disconnect(this WebSocket webSocket)
{ {
var data = GetData(webSocket); var data = GetConnectionInfo(webSocket);
data.ReceiveCancellationTokenSource.Cancel();
data.CompletionSource.SetResult(WebSocketHandleResult.Successful); data.CompletionSource.SetResult(WebSocketHandleResult.Successful);
Data.Remove(webSocket); webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
}
public static void DisconnectAll() WebSocketConnectionManager.Info.Remove(webSocket);
{
foreach (var (socket, _) in Data)
{
RemoveData(socket);
}
} }
} }
@@ -2,11 +2,11 @@
using CrystalConnector.Utilities; using CrystalConnector.Utilities;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace CrystalConnector.Handlers; namespace CrystalConnector.WebSockets;
public interface IWebSocketHandler public interface IWebSocketManager
{ {
public void StartHandle(HttpContext context, WebSocket socket, TaskCompletionSource<WebSocketHandleResult> taskCompletionSource); public Task StartHandle(HttpContext context, WebSocket socket, TaskCompletionSource<WebSocketHandleResult> taskCompletionSource);
public void Disconnect(WebSocket socket); public void Disconnect(WebSocket socket);
} }
@@ -0,0 +1,49 @@
using System.Formats.Cbor;
using System.Net;
using System.Net.WebSockets;
using CrystalConnector.Handlers;
using CrystalConnector.Utilities;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace CrystalConnector.WebSockets;
public class WebSocketManager : IWebSocketManager
{
private ILogger<WebSocketManager> Logger { get; }
private WebSocketHandler Handler { get; }
public WebSocketManager(ILogger<WebSocketManager> logger, WebSocketHandler handler)
{
Logger = logger;
Handler = handler;
}
public async Task StartHandle(HttpContext context, WebSocket webSocket, TaskCompletionSource<WebSocketHandleResult> taskCompletionSource)
{
var remoteEndPoint = new IPEndPoint(context.Connection.RemoteIpAddress!, context.Connection.RemotePort); // qyl27: we believe it is a tcp connection.
webSocket.AddConnectionInfo(context.Connection.Id, remoteEndPoint, taskCompletionSource);
await Receive(webSocket);
}
private async Task Receive(WebSocket webSocket)
{
var buffer = new byte[1024 * 4];
var receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!receiveResult.CloseStatus.HasValue)
{
var reader = new CborReader(new ReadOnlyMemory<byte>(buffer, 0, receiveResult.Count));
Handler.Handle(webSocket, reader);
receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
}
public void Disconnect(WebSocket webSocket)
{
webSocket.Disconnect();
}
}