diff --git a/CrystalConnector/Connector/MessageChannel.cs b/CrystalConnector/Connector/MessageChannel.cs new file mode 100644 index 0000000..0643dcd --- /dev/null +++ b/CrystalConnector/Connector/MessageChannel.cs @@ -0,0 +1,6 @@ +namespace CrystalConnector.Connector; + +public class MessageChannel +{ + +} \ No newline at end of file diff --git a/CrystalConnector/CrystalConnector.csproj b/CrystalConnector/CrystalConnector.csproj index 860f7d1..1608de9 100644 --- a/CrystalConnector/CrystalConnector.csproj +++ b/CrystalConnector/CrystalConnector.csproj @@ -8,15 +8,14 @@ - - - - - + + + + + - - + diff --git a/CrystalConnector/CrystalService.cs b/CrystalConnector/CrystalService.cs index ba9f5ee..dce6bad 100644 --- a/CrystalConnector/CrystalService.cs +++ b/CrystalConnector/CrystalService.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Configuration; +using CrystalConnector.Utilities; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using NLog; @@ -28,6 +29,7 @@ public class CrystalService : IHostedService private void OnStopping() { Logger.LogInformation("Stopping!"); + WebSocketExtension.DisconnectAll(); } private void OnStopped() diff --git a/CrystalConnector/Handlers/IWebSocketHandler.cs b/CrystalConnector/Handlers/IWebSocketHandler.cs index 24ecbc0..8344e47 100644 --- a/CrystalConnector/Handlers/IWebSocketHandler.cs +++ b/CrystalConnector/Handlers/IWebSocketHandler.cs @@ -1,4 +1,5 @@ using System.Net.WebSockets; +using CrystalConnector.Utilities; using Microsoft.AspNetCore.Http; namespace CrystalConnector.Handlers; diff --git a/CrystalConnector/Handlers/WebSocketHandler.cs b/CrystalConnector/Handlers/WebSocketHandler.cs index f8f14de..40cd485 100644 --- a/CrystalConnector/Handlers/WebSocketHandler.cs +++ b/CrystalConnector/Handlers/WebSocketHandler.cs @@ -1,5 +1,6 @@ using System.Net; using System.Net.WebSockets; +using CrystalConnector.Utilities; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; @@ -9,22 +10,33 @@ public class WebSocketHandler : IWebSocketHandler { private ILogger Logger { get; } - // Todo: qyl27: Maybe we need a MultiKeyMap? >> - private Dictionary>> WebSockets { get; } = new(); - public WebSocketHandler(ILogger logger) { Logger = logger; } - public void StartHandle(HttpContext context, WebSocket socket, TaskCompletionSource taskCompletionSource) + public async void StartHandle(HttpContext context, WebSocket webSocket, TaskCompletionSource taskCompletionSource) { - var remoteEndPoint = new IPEndPoint(context.Connection.RemoteIpAddress, context.Connection.RemotePort); - WebSockets.Add(remoteEndPoint, new Tuple>(socket, taskCompletionSource)); + var remoteEndPoint = new IPEndPoint(context.Connection.RemoteIpAddress!, context.Connection.RemotePort); // qyl27: we believe it is a tcp connection. + var receiveCancellationTokenSource = new CancellationTokenSource(); + webSocket.AddData(context.Connection.Id, remoteEndPoint, taskCompletionSource, receiveCancellationTokenSource); + await Handle(webSocket, receiveCancellationTokenSource.Token); } - public void Disconnect(WebSocket socket) + private async Task Handle(WebSocket webSocket, CancellationToken cancellationToken) { + var buffer = new byte[1024 * 4]; + WebSocketReceiveResult receiveResult; + + do + { + receiveResult = await webSocket.ReceiveAsync(new ArraySegment(buffer), cancellationToken); + } while (!cancellationToken.IsCancellationRequested && !receiveResult.CloseStatus.HasValue); + } + + public void Disconnect(WebSocket webSocket) + { + webSocket.RemoveData(); } } \ No newline at end of file diff --git a/CrystalConnector/Startup.cs b/CrystalConnector/Startup.cs index 7244349..01aa160 100644 --- a/CrystalConnector/Startup.cs +++ b/CrystalConnector/Startup.cs @@ -1,4 +1,5 @@ using CrystalConnector.Handlers; +using CrystalConnector.Utilities; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/CrystalConnector/Utilities/WebSocketData.cs b/CrystalConnector/Utilities/WebSocketData.cs new file mode 100644 index 0000000..f4b2d1a --- /dev/null +++ b/CrystalConnector/Utilities/WebSocketData.cs @@ -0,0 +1,19 @@ +using System.Net; +using CrystalConnector.Connector; + +namespace CrystalConnector.Utilities; + +public class WebSocketData +{ + public required string Id { get; set; } + + public required IPEndPoint IpEndPoint { get; set; } + + public required TaskCompletionSource CompletionSource { get; set; } + + public required CancellationTokenSource ReceiveCancellationTokenSource { get; set; } + + public bool Authorized { get; set; } = false; + + public List RegisteredChannels { get; } = new(); +} \ No newline at end of file diff --git a/CrystalConnector/Utilities/WebSocketExtension.cs b/CrystalConnector/Utilities/WebSocketExtension.cs new file mode 100644 index 0000000..ea9cf1d --- /dev/null +++ b/CrystalConnector/Utilities/WebSocketExtension.cs @@ -0,0 +1,44 @@ +using System.Net; +using System.Net.WebSockets; + +namespace CrystalConnector.Utilities; + +public static class WebSocketExtension +{ + private static Dictionary Data { get; } = new(); + + public static void AddData(this WebSocket webSocket, string id, IPEndPoint ip, + TaskCompletionSource taskCompletionSource, + CancellationTokenSource receiveCancellationTokenSource) + { + Data.Add(webSocket, new WebSocketData + { + Id = id, + IpEndPoint = ip, + CompletionSource = taskCompletionSource, + ReceiveCancellationTokenSource = receiveCancellationTokenSource + }); + } + + public static WebSocketData GetData(this WebSocket webSocket) + { + return Data[webSocket]; + } + + public static void RemoveData(this WebSocket webSocket) + { + var data = GetData(webSocket); + data.ReceiveCancellationTokenSource.Cancel(); + data.CompletionSource.SetResult(WebSocketHandleResult.Successful); + + Data.Remove(webSocket); + } + + public static void DisconnectAll() + { + foreach (var (socket, _) in Data) + { + RemoveData(socket); + } + } +} \ No newline at end of file diff --git a/CrystalConnector/Handlers/WebSocketHandleResult.cs b/CrystalConnector/Utilities/WebSocketHandleResult.cs similarity index 58% rename from CrystalConnector/Handlers/WebSocketHandleResult.cs rename to CrystalConnector/Utilities/WebSocketHandleResult.cs index 9570370..58242bf 100644 --- a/CrystalConnector/Handlers/WebSocketHandleResult.cs +++ b/CrystalConnector/Utilities/WebSocketHandleResult.cs @@ -1,4 +1,4 @@ -namespace CrystalConnector.Handlers; +namespace CrystalConnector.Utilities; public enum WebSocketHandleResult { diff --git a/CrystalConnector/config.json b/CrystalConnector/config.json index af58a73..c4f45d7 100644 --- a/CrystalConnector/config.json +++ b/CrystalConnector/config.json @@ -12,5 +12,10 @@ } } ] + }, + "Connector": { + "Auth": { + "Secret": "qyl27IsHere!" + } } } \ No newline at end of file