114 lines
3.4 KiB
C#
114 lines
3.4 KiB
C#
using System;
|
|
|
|
namespace XWorld.Framework.Protocol
|
|
{
|
|
public static class DevDiscovery
|
|
{
|
|
public const int Port = 48923;
|
|
public const uint ProtoVersion = 1;
|
|
public static readonly byte[] Magic = { 0x58, 0x57, 0x44, 0x4C };
|
|
public const byte TypeQuery = 1;
|
|
public const byte TypeReply = 2;
|
|
}
|
|
|
|
public struct DevDiscoveryQuery
|
|
{
|
|
public uint ProtoVersion;
|
|
public uint Nonce;
|
|
public string Token;
|
|
}
|
|
|
|
public struct DevDiscoveryReply
|
|
{
|
|
public uint ProtoVersion;
|
|
public uint Nonce;
|
|
public string ServerName;
|
|
public string GatewayUrl;
|
|
public string ResourceBaseUrl;
|
|
public string Token;
|
|
}
|
|
|
|
public static class DevDiscoveryCodec
|
|
{
|
|
public static byte[] EncodeQuery(DevDiscoveryQuery q)
|
|
{
|
|
var w = new PacketWriter(32);
|
|
WriteHeader(w, DevDiscovery.TypeQuery);
|
|
w.WriteVarUInt(q.ProtoVersion);
|
|
w.WriteVarUInt(q.Nonce);
|
|
w.WriteString(q.Token);
|
|
return w.ToArray();
|
|
}
|
|
|
|
public static byte[] EncodeReply(DevDiscoveryReply r)
|
|
{
|
|
var w = new PacketWriter(96);
|
|
WriteHeader(w, DevDiscovery.TypeReply);
|
|
w.WriteVarUInt(r.ProtoVersion);
|
|
w.WriteVarUInt(r.Nonce);
|
|
w.WriteString(r.ServerName);
|
|
w.WriteString(r.GatewayUrl);
|
|
w.WriteString(r.ResourceBaseUrl);
|
|
w.WriteString(r.Token);
|
|
return w.ToArray();
|
|
}
|
|
|
|
public static bool TryDecodeQuery(byte[] data, out DevDiscoveryQuery q)
|
|
{
|
|
q = default;
|
|
try
|
|
{
|
|
var r = new PacketReader(data);
|
|
if (!ReadAndCheckHeader(r, DevDiscovery.TypeQuery)) return false;
|
|
q.ProtoVersion = r.ReadVarUInt();
|
|
q.Nonce = r.ReadVarUInt();
|
|
q.Token = r.ReadString();
|
|
return true;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static bool TryDecodeReply(byte[] data, out DevDiscoveryReply reply)
|
|
{
|
|
reply = default;
|
|
try
|
|
{
|
|
var r = new PacketReader(data);
|
|
if (!ReadAndCheckHeader(r, DevDiscovery.TypeReply)) return false;
|
|
reply.ProtoVersion = r.ReadVarUInt();
|
|
reply.Nonce = r.ReadVarUInt();
|
|
reply.ServerName = r.ReadString();
|
|
reply.GatewayUrl = r.ReadString();
|
|
reply.ResourceBaseUrl = r.ReadString();
|
|
reply.Token = r.ReadString();
|
|
return true;
|
|
}
|
|
catch (FormatException)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static void WriteHeader(PacketWriter w, byte type)
|
|
{
|
|
for (int i = 0; i < DevDiscovery.Magic.Length; i++)
|
|
{
|
|
w.WriteByte(DevDiscovery.Magic[i]);
|
|
}
|
|
w.WriteByte(type);
|
|
}
|
|
|
|
private static bool ReadAndCheckHeader(PacketReader r, byte expectedType)
|
|
{
|
|
for (int i = 0; i < DevDiscovery.Magic.Length; i++)
|
|
{
|
|
if (r.ReadByte() != DevDiscovery.Magic[i]) return false;
|
|
}
|
|
return r.ReadByte() == expectedType;
|
|
}
|
|
}
|
|
}
|