✨ Websocket receive.

Signed-off-by: 秋雨落 <i@rain.cx>
This commit is contained in:
秋雨落
2023-09-13 09:06:54 +08:00
parent f231cf63e5
commit cb14d7ff74
10 changed files with 105 additions and 16 deletions
@@ -0,0 +1,6 @@
namespace CrystalConnector.Connector;
public class MessageChannel
{
}
+6 -7
View File
@@ -8,15 +8,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0-preview.7.23375.6" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0-preview.7.23375.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0-preview.7.23375.6" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0-preview.7.23375.6" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0-preview.7.23375.6" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="NLog" Version="5.2.4" /> <PackageReference Include="NLog" Version="5.2.4" />
<PackageReference Include="NLog.Extensions.Hosting" Version="5.3.4" /> <PackageReference Include="NLog.Extensions.Hosting" Version="5.3.4" />
<PackageReference Include="Spectre.Console" Version="0.47.1-preview.0.12" /> <PackageReference Include="System.Formats.Cbor" Version="8.0.0-rc.1.23419.4" />
<PackageReference Include="Telegram.Bot" Version="19.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+3 -1
View File
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Configuration; using CrystalConnector.Utilities;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NLog; using NLog;
@@ -28,6 +29,7 @@ public class CrystalService : IHostedService
private void OnStopping() private void OnStopping()
{ {
Logger.LogInformation("Stopping!"); Logger.LogInformation("Stopping!");
WebSocketExtension.DisconnectAll();
} }
private void OnStopped() private void OnStopped()
@@ -1,4 +1,5 @@
using System.Net.WebSockets; using System.Net.WebSockets;
using CrystalConnector.Utilities;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
namespace CrystalConnector.Handlers; namespace CrystalConnector.Handlers;
+19 -7
View File
@@ -1,5 +1,6 @@
using System.Net; using System.Net;
using System.Net.WebSockets; using System.Net.WebSockets;
using CrystalConnector.Utilities;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -9,22 +10,33 @@ public class WebSocketHandler : IWebSocketHandler
{ {
private ILogger<WebSocketHandler> Logger { get; } private ILogger<WebSocketHandler> Logger { get; }
// Todo: qyl27: Maybe we need a MultiKeyMap? <string Id, IPEndPoint ip, Tuple<WebSocket, TaskCompletionSource<WebSocketHandleResult>>>
private Dictionary<IPEndPoint, Tuple<WebSocket, TaskCompletionSource<WebSocketHandleResult>>> WebSockets { get; } = new();
public WebSocketHandler(ILogger<WebSocketHandler> logger) public WebSocketHandler(ILogger<WebSocketHandler> logger)
{ {
Logger = logger; Logger = logger;
} }
public void StartHandle(HttpContext context, WebSocket socket, TaskCompletionSource<WebSocketHandleResult> taskCompletionSource) public async void StartHandle(HttpContext context, WebSocket webSocket, TaskCompletionSource<WebSocketHandleResult> taskCompletionSource)
{ {
var remoteEndPoint = new IPEndPoint(context.Connection.RemoteIpAddress, context.Connection.RemotePort); var remoteEndPoint = new IPEndPoint(context.Connection.RemoteIpAddress!, context.Connection.RemotePort); // qyl27: we believe it is a tcp connection.
WebSockets.Add(remoteEndPoint, new Tuple<WebSocket, TaskCompletionSource<WebSocketHandleResult>>(socket, taskCompletionSource)); 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<byte>(buffer), cancellationToken);
} while (!cancellationToken.IsCancellationRequested && !receiveResult.CloseStatus.HasValue);
}
public void Disconnect(WebSocket webSocket)
{
webSocket.RemoveData();
} }
} }
+1
View File
@@ -1,4 +1,5 @@
using CrystalConnector.Handlers; using CrystalConnector.Handlers;
using CrystalConnector.Utilities;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -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<WebSocketHandleResult> CompletionSource { get; set; }
public required CancellationTokenSource ReceiveCancellationTokenSource { get; set; }
public bool Authorized { get; set; } = false;
public List<MessageChannel> RegisteredChannels { get; } = new();
}
@@ -0,0 +1,44 @@
using System.Net;
using System.Net.WebSockets;
namespace CrystalConnector.Utilities;
public static class WebSocketExtension
{
private static Dictionary<WebSocket, WebSocketData> Data { get; } = new();
public static void AddData(this WebSocket webSocket, string id, IPEndPoint ip,
TaskCompletionSource<WebSocketHandleResult> 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);
}
}
}
@@ -1,4 +1,4 @@
namespace CrystalConnector.Handlers; namespace CrystalConnector.Utilities;
public enum WebSocketHandleResult public enum WebSocketHandleResult
{ {
+5
View File
@@ -12,5 +12,10 @@
} }
} }
] ]
},
"Connector": {
"Auth": {
"Secret": "qyl27IsHere!"
}
} }
} }