mirror of
https://github.com/MeowCraftMC/CrystalConnector
synced 2025-05-22 02:43:00 +00:00
✨ V2 (#1)
* 🚧 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>
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||
<Authors>qyl27,MeowCraftMC</Authors>
|
||||
<RepositoryUrl>https://github.com/MeowCraftMC/CrystalConnector</RepositoryUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
|
||||
<IncludeSymbols>True</IncludeSymbols>
|
||||
<PackageProjectUrl>https://github.com/MeowCraftMC/CrystalConnector</PackageProjectUrl>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.25.1" />
|
||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.25.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="proto\messages.proto" GrpcServices="Client" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Messages\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
||||
using CrystalConnector.Protocol.Messages;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace CrystalConnector.Protocol.Packets.C2S;
|
||||
|
||||
public class AuthenticatePacket : IPacket
|
||||
{
|
||||
public NamespacedName ClientId { get; set; }
|
||||
public string ClientName { get; set; }
|
||||
public string Key { get; set; }
|
||||
|
||||
public List<Channel> Channels { get; } = [];
|
||||
|
||||
public AuthenticatePacket(NamespacedName clientId, string clientName, string key, List<Channel> channels)
|
||||
{
|
||||
ClientId = clientId;
|
||||
ClientName = clientName;
|
||||
Key = key;
|
||||
Channels.AddRange(channels);
|
||||
}
|
||||
|
||||
public AuthenticatePacket(byte[] bytes)
|
||||
{
|
||||
Read(bytes);
|
||||
}
|
||||
|
||||
public AuthenticatePacket()
|
||||
{
|
||||
}
|
||||
|
||||
public void Read(byte[] bytes)
|
||||
{
|
||||
var message = Authenticate.Parser.ParseFrom(bytes);
|
||||
|
||||
ClientId = message.ClientId;
|
||||
ClientName = message.ClientName;
|
||||
Key = message.SecretKey;
|
||||
Channels.AddRange(message.Channels);
|
||||
}
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
var message = new Authenticate
|
||||
{
|
||||
ClientId = ClientId,
|
||||
ClientName = ClientName,
|
||||
SecretKey = Key
|
||||
};
|
||||
message.Channels.AddRange(Channels);
|
||||
|
||||
return message.ToByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using CrystalConnector.Protocol.Messages;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace CrystalConnector.Protocol.Packets.C2S;
|
||||
|
||||
public class PublishPacket : IPacket
|
||||
{
|
||||
public NamespacedName Channel { get; set; }
|
||||
public string Payload { get; set; }
|
||||
|
||||
public PublishPacket(NamespacedName channel, string payload)
|
||||
{
|
||||
Channel = channel;
|
||||
Payload = payload;
|
||||
}
|
||||
|
||||
public PublishPacket(byte[] bytes)
|
||||
{
|
||||
Read(bytes);
|
||||
}
|
||||
|
||||
public PublishPacket()
|
||||
{
|
||||
}
|
||||
|
||||
public void Read(byte[] bytes)
|
||||
{
|
||||
var message = Publish.Parser.ParseFrom(bytes);
|
||||
Channel = message.Channel;
|
||||
Payload = message.Payload;
|
||||
}
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
var message = new Publish
|
||||
{
|
||||
Channel = Channel,
|
||||
Payload = Payload
|
||||
};
|
||||
|
||||
return message.ToByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using CrystalConnector.Protocol.Packets.C2S;
|
||||
using CrystalConnector.Protocol.Packets.S2C;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace CrystalConnector.Protocol.Packets;
|
||||
|
||||
public interface IPacket
|
||||
{
|
||||
public void Read(byte[] bytes);
|
||||
|
||||
public byte[] Write();
|
||||
|
||||
public static IPacket? From(byte[] data)
|
||||
{
|
||||
var result = TryForm<AuthenticatePacket>(data);
|
||||
if (result is not null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = TryForm<PublishPacket>(data);
|
||||
if (result is not null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = TryForm<ForwardPacket>(data);
|
||||
if (result is not null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = TryForm<ResultPacket>(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IPacket? TryForm<T>(byte[] data) where T : IPacket, new()
|
||||
{
|
||||
try
|
||||
{
|
||||
var message = new T();
|
||||
message.Read(data);
|
||||
return message;
|
||||
}
|
||||
catch (InvalidProtocolBufferException ex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using CrystalConnector.Protocol.Messages;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace CrystalConnector.Protocol.Packets.S2C;
|
||||
|
||||
public class ForwardPacket : IPacket
|
||||
{
|
||||
public string Publisher { get; set; }
|
||||
public NamespacedName Channel { get; set; }
|
||||
public string Payload { get; set; }
|
||||
|
||||
public ForwardPacket(string publisher, (string Namespace, string Name) channel, string payload)
|
||||
{
|
||||
Publisher = publisher;
|
||||
Channel = new NamespacedName
|
||||
{
|
||||
Namespace = channel.Namespace,
|
||||
Name = channel.Name
|
||||
};
|
||||
Payload = payload;
|
||||
}
|
||||
|
||||
public ForwardPacket(byte[] bytes)
|
||||
{
|
||||
Read(bytes);
|
||||
}
|
||||
|
||||
public ForwardPacket()
|
||||
{
|
||||
}
|
||||
|
||||
public void Read(byte[] bytes)
|
||||
{
|
||||
var message = Forward.Parser.ParseFrom(bytes);
|
||||
Publisher = message.Publisher;
|
||||
Channel = message.Channel;
|
||||
Payload = message.Payload;
|
||||
}
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
var message = new Forward
|
||||
{
|
||||
Publisher = Publisher,
|
||||
Channel = Channel,
|
||||
Payload = Payload
|
||||
};
|
||||
|
||||
return message.ToByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using CrystalConnector.Protocol.Messages;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace CrystalConnector.Protocol.Packets.S2C;
|
||||
|
||||
public class ResultPacket : IPacket
|
||||
{
|
||||
public Result.ResultOneofCase ResultOneofCase { get; set; }
|
||||
public Error? Error { get; set; }
|
||||
|
||||
public ResultPacket()
|
||||
{
|
||||
ResultOneofCase = Result.ResultOneofCase.Successful;
|
||||
}
|
||||
|
||||
public ResultPacket(Error error)
|
||||
{
|
||||
ResultOneofCase = Result.ResultOneofCase.Error;
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public ResultPacket(byte[] bytes)
|
||||
{
|
||||
Read(bytes);
|
||||
}
|
||||
|
||||
public void Read(byte[] bytes)
|
||||
{
|
||||
var message = Result.Parser.ParseFrom(bytes);
|
||||
ResultOneofCase = message.ResultCase;
|
||||
|
||||
if (message.HasError)
|
||||
{
|
||||
Error = message.Error;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Write()
|
||||
{
|
||||
var message = ResultOneofCase switch
|
||||
{
|
||||
Result.ResultOneofCase.None => new Result
|
||||
{
|
||||
Error = Messages.Error.Unknown
|
||||
},
|
||||
Result.ResultOneofCase.Successful => new Result
|
||||
{
|
||||
Successful = new Successful()
|
||||
},
|
||||
Result.ResultOneofCase.Error => new Result
|
||||
{
|
||||
Error = Error!.Value
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
return message.ToByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
# CrystalConnector.Protocol
|
||||
|
||||
## Generate Proto file
|
||||
|
||||
```shell
|
||||
protoc.exe --proto_path=proto --csharp_out=Messages proto\messages.proto
|
||||
```
|
||||
@@ -0,0 +1,25 @@
|
||||
using CrystalConnector.Protocol.Messages;
|
||||
|
||||
namespace CrystalConnector.Protocol.Utilities;
|
||||
|
||||
public static class PacketHelperExtensions
|
||||
{
|
||||
public static (string Namespace, string Name) ToTuple(this NamespacedName name)
|
||||
{
|
||||
return (name.Namespace, name.Name);
|
||||
}
|
||||
|
||||
public static NamespacedName ToName(this (string Namespace, string Name) name)
|
||||
{
|
||||
return new NamespacedName
|
||||
{
|
||||
Namespace = name.Namespace,
|
||||
Name = name.Name
|
||||
};
|
||||
}
|
||||
|
||||
public static string ToIdString(this (string Namespace, string Name) name)
|
||||
{
|
||||
return $"{name.Namespace}:{name.Name}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
syntax = "proto3";
|
||||
option csharp_namespace = "CrystalConnector.Protocol.Messages";
|
||||
|
||||
package CrystalConnector;
|
||||
|
||||
message NamespacedName {
|
||||
string namespace = 1;
|
||||
string name = 2;
|
||||
}
|
||||
|
||||
enum MessageDirection {
|
||||
NONE = 0;
|
||||
INCOMING = 1;
|
||||
OUTGOING = 2;
|
||||
ALL = 3;
|
||||
}
|
||||
|
||||
message Successful {
|
||||
}
|
||||
|
||||
enum Error {
|
||||
UNKNOWN = 0;
|
||||
AUTHENTICATED = 1;
|
||||
NAME_EXISTS = 2;
|
||||
UNAUTHENTICATED = 3;
|
||||
UNREGISTERED_CHANNEL = 4;
|
||||
INTERNAL = 5;
|
||||
}
|
||||
|
||||
message Result {
|
||||
oneof result {
|
||||
Successful successful = 1;
|
||||
Error error = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message Authenticate {
|
||||
NamespacedName client_id = 1;
|
||||
string client_name = 2;
|
||||
string secret_key = 3;
|
||||
|
||||
repeated Channel channels = 4;
|
||||
}
|
||||
|
||||
message Channel {
|
||||
NamespacedName id = 1;
|
||||
MessageDirection direction = 2;
|
||||
}
|
||||
|
||||
message Publish {
|
||||
NamespacedName channel = 1;
|
||||
string payload = 2;
|
||||
}
|
||||
|
||||
message Forward {
|
||||
string publisher = 1;
|
||||
NamespacedName channel = 2;
|
||||
string payload = 3;
|
||||
}
|
||||
Reference in New Issue
Block a user