mirror of
https://github.com/MeowCraftMC/CrystalConnector
synced 2025-05-22 02:43:00 +00:00
* 🚧 WIP v2. Signed-off-by: 秋雨落 <i@rain.cx> * 🚧 WIP v2 * 2. Signed-off-by: 秋雨落 <i@rain.cx> * ✨ It works? Signed-off-by: 秋雨落 <i@rain.cx> * ✨ Publish to nexus. Signed-off-by: 秋雨落 <i@rain.cx> --------- Signed-off-by: 秋雨落 <i@rain.cx>
118 lines
4.6 KiB
C#
118 lines
4.6 KiB
C#
using System.Net.WebSockets;
|
|
using CrystalConnector.Configs;
|
|
using CrystalConnector.Connector;
|
|
using CrystalConnector.Protocol.Messages;
|
|
using CrystalConnector.Protocol.Packets;
|
|
using CrystalConnector.Protocol.Packets.C2S;
|
|
using CrystalConnector.Protocol.Packets.S2C;
|
|
using CrystalConnector.Protocol.Utilities;
|
|
using CrystalConnector.Utilities;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace CrystalConnector.Handlers;
|
|
|
|
public class WebSocketHandler
|
|
{
|
|
private ConfigAccessor Config { get; }
|
|
|
|
private ILogger<WebSocketHandler> Logger { get; }
|
|
|
|
public WebSocketHandler(ConfigAccessor config, ILogger<WebSocketHandler> logger)
|
|
{
|
|
Config = config;
|
|
Logger = logger;
|
|
}
|
|
|
|
public async Task<IPacket> Handle(WebSocket webSocket, byte[] data)
|
|
{
|
|
var packet = IPacket.From(data);
|
|
switch (packet)
|
|
{
|
|
case AuthenticatePacket authenticatePacket:
|
|
{
|
|
var clientId = (authenticatePacket.ClientId.Namespace, authenticatePacket.ClientId.Name);
|
|
|
|
if (authenticatePacket.Key == Config.GetSecretKey())
|
|
{
|
|
if (WebSocketConnectionManager.HaveClientRegistered(clientId))
|
|
{
|
|
Logger.LogInformation("Client {Id} tried authorize with name {Name}, but it is already authorized!", clientId.ToIdString(), authenticatePacket.ClientName);
|
|
return new ResultPacket(Error.NameExists);
|
|
}
|
|
|
|
Logger.LogInformation("Client {Name}({Id}) authorized", authenticatePacket.ClientName, clientId.ToIdString());
|
|
|
|
var connectionInfo = webSocket.GetConnectionInfo();
|
|
|
|
connectionInfo.Authenticated = true;
|
|
connectionInfo.ClientId = clientId;
|
|
connectionInfo.Name = authenticatePacket.ClientName;
|
|
|
|
var channels = connectionInfo.RegisteredChannels;
|
|
|
|
foreach (var channel in authenticatePacket.Channels)
|
|
{
|
|
var id = channel.Id.ToTuple();
|
|
if (channels.TryGetValue(id, out var chan))
|
|
{
|
|
chan.Direction = channel.Direction;
|
|
}
|
|
else
|
|
{
|
|
channels.Add(id, new MessageChannel
|
|
{
|
|
Id = id,
|
|
Direction = channel.Direction
|
|
});
|
|
}
|
|
}
|
|
|
|
return new ResultPacket();
|
|
}
|
|
|
|
Logger.LogWarning("Client {Name}({Id}) auth failed with wrong key!", authenticatePacket.ClientName, clientId.ToIdString());
|
|
return new ResultPacket(Error.Unauthenticated);
|
|
}
|
|
case PublishPacket publishPacket:
|
|
{
|
|
var connectionInfo = webSocket.GetConnectionInfo();
|
|
var id = publishPacket.Channel.ToTuple();
|
|
|
|
if (!connectionInfo.Authenticated)
|
|
{
|
|
return new ResultPacket(Error.Unauthenticated);
|
|
}
|
|
|
|
if (!connectionInfo.RegisteredChannels.TryGetValue(id, out var registered)
|
|
|| registered.Direction == MessageDirection.Outgoing
|
|
|| registered.Direction == MessageDirection.All)
|
|
{
|
|
Logger.LogWarning("Channel {Channel}(Direction: {Direction}) have not been registered by Client {Name}({Id})",
|
|
id.ToIdString(), MessageDirection.Outgoing, webSocket.GetConnectionInfo().Name, webSocket.GetConnectionInfo().Id);
|
|
return new ResultPacket(Error.UnregisteredChannel);
|
|
}
|
|
|
|
var name = webSocket.GetConnectionInfo().Name;
|
|
await WebSocketConnectionManager.Broadcast(name!, id, publishPacket.Payload);
|
|
|
|
if (Config.IsDebug())
|
|
{
|
|
Logger.LogDebug("Client {Name}({Id}) send data in {Channel}: {Data}",
|
|
name, webSocket.GetConnectionInfo().ClientId!.Value.ToIdString(), id.ToIdString(), publishPacket.Payload);
|
|
}
|
|
|
|
return new ResultPacket();
|
|
}
|
|
case ForwardPacket forwardPacket:
|
|
{
|
|
break;
|
|
}
|
|
case ResultPacket resultPacket:
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return new ResultPacket();
|
|
}
|
|
} |