GameServer + packet types, we aren't parsing yet
This commit is contained in:
parent
f753a0ffc4
commit
0eacd1bfe2
|
@ -8,7 +8,6 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Config.Net" Version="5.1.5" />
|
<PackageReference Include="Config.Net" Version="5.1.5" />
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.24.3" />
|
|
||||||
<PackageReference Include="MongoDB.Driver" Version="2.21.0" />
|
<PackageReference Include="MongoDB.Driver" Version="2.21.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace AscNet.Common.Database
|
||||||
public static Account Create(string username, string password)
|
public static Account Create(string username, string password)
|
||||||
{
|
{
|
||||||
if (collection.AsQueryable().FirstOrDefault(x => x.Username == username) is not null)
|
if (collection.AsQueryable().FirstOrDefault(x => x.Username == username) is not null)
|
||||||
throw new ArgumentException("Username is already registered!", "username");
|
throw new ArgumentException("Username is already registered!", nameof(username));
|
||||||
|
|
||||||
Account account = new()
|
Account account = new()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
namespace AscNet.Common.Util
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace AscNet.Common.Util
|
||||||
{
|
{
|
||||||
public static class Crypto
|
public static class Crypto
|
||||||
{
|
{
|
||||||
|
@ -11,5 +13,78 @@
|
||||||
|
|
||||||
return encryptedData;
|
return encryptedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class HaruCrypt
|
||||||
|
{
|
||||||
|
private static readonly byte[] key = new byte[] { 103, 40, 227, 236, 173, 175, 148, 243, 66, 252, 58, 22, 68, 192, 159, 15, 187, 15, 15, 29, 209, 209, 212, 66, 104, 16, 252, 194, 227, 14, 116, 112, 196, 221, 5, 1, 4, 173, 165, 69, 45, 193, 95, 10, 67, 38, 167, 239, 96, 184, 133, 75, 152, 196, 36, 121, 251, 7, 73, 82, 219, 25, 118, 70, 153, 232, 120, 120, 147, 10, 88, 106, 214, 187, 216, 49, 224, 57, 1, 233, 110, 40, 65, 85, 246, 197, 4, 20, 56, 74, 245, 41, 63, 169, 188, 104, 89, 49, 115, 254, 100, 77, 79, 11, 148, 242, 95, 88, 241, 111, 48, 130, 169, 200, 224, 135, 121, 161, 72, 84, 5, 100, 135, 70, 141, 94, 244, 114, 58, 28, 87, 181, 205, 221, 154, 184, 197, 98, 210, 202, 252, 124, 144, 9, 112, 163, 24, 254, 119, 188, 5, 230, 40, 79, 171, 17, 156, 212, 134, 41, 79, 134, 26, 251, 123, 219, 191, 136, 21, 84, 192, 91, 24, 33, 68, 101, 85, 61, 186, 215, 191, 37, 45, 51, 117, 227, 14, 145, 56, 43, 32, 67, 48, 98, 192, 41, 136, 223, 50, 163, 97, 251, 174, 59, 59, 147, 237, 177, 31, 159, 52, 243, 245, 247, 148, 139, 21, 92, 139, 80, 47, 4, 105, 59, 227, 220, 180, 231, 176, 187, 205, 203, 148, 121, 98, 90, 87, 131, 245, 3, 63, 239, 57, 117, 102, 134, 40, 172, 60, 128, 108, 102, 216, 247, 133, 102 };
|
||||||
|
private static readonly RSACryptoServiceProvider rsa = new();
|
||||||
|
private static readonly byte[] signature = new byte[128];
|
||||||
|
#pragma warning disable SYSLIB0021 // Type or member is obsolete
|
||||||
|
private static readonly SHA1 sha = new SHA1CryptoServiceProvider();
|
||||||
|
#pragma warning restore SYSLIB0021 // Type or member is obsolete
|
||||||
|
private const string PUBLIC_KEY = "<RSAKeyValue><Modulus>kZE/f0ifi0DH3uP3KCWOPqTyQ3MsQKHf9X4Z65S36s226RkdkZL2kHTz20n+IlOvGChi3ByDMFLawlyB0MCW94WDnc1Mc/PtVKo6D8gBEcSvdjDbhC4Ly0f2hMHS/SNdGPMAMkEWGNvIvfuT1TEaWTPsxRLZbfASp2KPG7Wjdck=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
|
||||||
|
|
||||||
|
static HaruCrypt()
|
||||||
|
{
|
||||||
|
rsa.FromXmlString(PUBLIC_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Encrypt(byte[] content)
|
||||||
|
{
|
||||||
|
Encrypt(content, 0, content.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Encrypt(byte[] content, int offset, int count)
|
||||||
|
{
|
||||||
|
int num = count % key.Length;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
int num2 = i + offset;
|
||||||
|
int num3 = (int)content[num2];
|
||||||
|
num3 ^= (int)key[num];
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
num3 ^= (int)content[num2 - 1];
|
||||||
|
}
|
||||||
|
num3 ^= (int)key[i % key.Length];
|
||||||
|
int num4 = ((int)((i + 1 < count) ? content[num2 + 1] : 0) + count) % 8;
|
||||||
|
num3 = (num3 << 8 - num4 | num3 >> num4);
|
||||||
|
content[num2] = (byte)num3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Decrypt(byte[] content)
|
||||||
|
{
|
||||||
|
Decrypt(content, 0, content.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Decrypt(byte[] bytes, int offset, int count)
|
||||||
|
{
|
||||||
|
int num = count % key.Length;
|
||||||
|
for (int i = count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int num2 = i + offset;
|
||||||
|
int num3 = (int)bytes[num2];
|
||||||
|
int num4 = ((int)((i + 1 < count) ? bytes[num2 + 1] : 0) + count) % 8;
|
||||||
|
num3 = (num3 >> 8 - num4 | num3 << num4);
|
||||||
|
num3 ^= (int)key[i % key.Length];
|
||||||
|
if (num2 > offset)
|
||||||
|
{
|
||||||
|
num3 ^= (int)bytes[num2 - 1];
|
||||||
|
}
|
||||||
|
num3 ^= (int)key[num];
|
||||||
|
bytes[num2] = (byte)num3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool Verify(byte[] content, ref int offset, ref int count)
|
||||||
|
{
|
||||||
|
Buffer.BlockCopy(content, offset, signature, 0, signature.Length);
|
||||||
|
offset += signature.Length;
|
||||||
|
count -= signature.Length;
|
||||||
|
byte[] hash = sha.ComputeHash(content, offset, count);
|
||||||
|
return rsa.VerifyHash(hash, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MessagePack" Version="2.5.129" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AscNet.Common\AscNet.Common.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,76 @@
|
||||||
|
using MessagePack;
|
||||||
|
|
||||||
|
namespace AscNet.GameServer
|
||||||
|
{
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
[MessagePackObject(false)]
|
||||||
|
public class Packet
|
||||||
|
{
|
||||||
|
[Key(0)]
|
||||||
|
public int No;
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
|
public ContentType Type;
|
||||||
|
|
||||||
|
[Key(2)]
|
||||||
|
public byte[] Content;
|
||||||
|
|
||||||
|
public enum ContentType
|
||||||
|
{
|
||||||
|
Request,
|
||||||
|
Response,
|
||||||
|
Push,
|
||||||
|
Exception
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessagePackObject(false)]
|
||||||
|
public class Request
|
||||||
|
{
|
||||||
|
[Key(0)]
|
||||||
|
public int Id;
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
[Key(2)]
|
||||||
|
public byte[] Content;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessagePackObject(false)]
|
||||||
|
public class Response
|
||||||
|
{
|
||||||
|
[Key(0)]
|
||||||
|
public int Id;
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
[Key(2)]
|
||||||
|
public byte[] Content;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessagePackObject(false)]
|
||||||
|
public class Push
|
||||||
|
{
|
||||||
|
[Key(0)]
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
|
public byte[] Content;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MessagePackObject(false)]
|
||||||
|
public class Exception
|
||||||
|
{
|
||||||
|
[Key(0)]
|
||||||
|
public int Id;
|
||||||
|
|
||||||
|
[Key(1)]
|
||||||
|
public int Code;
|
||||||
|
|
||||||
|
[Key(2)]
|
||||||
|
public string Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using System.Net;
|
||||||
|
using AscNet.Common.Util;
|
||||||
|
|
||||||
|
namespace AscNet.GameServer
|
||||||
|
{
|
||||||
|
public class Server
|
||||||
|
{
|
||||||
|
public static readonly Logger c = new(nameof(GameServer), ConsoleColor.Cyan);
|
||||||
|
public readonly Dictionary<string, Session> Sessions = new();
|
||||||
|
private static Server? _instance;
|
||||||
|
private readonly TcpListener listener;
|
||||||
|
|
||||||
|
public static Server Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _instance ??= new Server();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server()
|
||||||
|
{
|
||||||
|
listener = new(IPAddress.Parse("0.0.0.0"), Common.Common.config.GameServer.Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
for (; ; )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
listener.Start();
|
||||||
|
c.Log($"{nameof(GameServer)} started and listening on port {Common.Common.config.GameServer.Port}");
|
||||||
|
|
||||||
|
for (; ; )
|
||||||
|
{
|
||||||
|
TcpClient tcpClient = listener.AcceptTcpClient();
|
||||||
|
string id = tcpClient.Client.RemoteEndPoint!.ToString()!;
|
||||||
|
|
||||||
|
c.Warn($"{id} connected");
|
||||||
|
Sessions.Add(id, new Session(id, tcpClient));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
c.Error("TCP listener error: " + ex.Message);
|
||||||
|
c.Log("Waiting 3 seconds before restarting...");
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
using System.Net.Sockets;
|
||||||
|
using AscNet.Common.Util;
|
||||||
|
|
||||||
|
namespace AscNet.GameServer
|
||||||
|
{
|
||||||
|
public class Session
|
||||||
|
{
|
||||||
|
public readonly string id;
|
||||||
|
public readonly TcpClient client;
|
||||||
|
public readonly Logger c;
|
||||||
|
private long lastPacketTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
|
// private ushort packetNo = 0;
|
||||||
|
|
||||||
|
public Session(string id, TcpClient tcpClient)
|
||||||
|
{
|
||||||
|
this.id = id;
|
||||||
|
client = tcpClient;
|
||||||
|
c = new(id, ConsoleColor.DarkGray);
|
||||||
|
|
||||||
|
Task.Run(ClientLoop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void ClientLoop()
|
||||||
|
{
|
||||||
|
NetworkStream stream = client.GetStream();
|
||||||
|
byte[] msg = new byte[1 << 16];
|
||||||
|
|
||||||
|
while (client.Connected)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Array.Clear(msg, 0, msg.Length);
|
||||||
|
int len = stream.Read(msg, 0, msg.Length);
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
lastPacketTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await Task.Delay(10);
|
||||||
|
// 10 sec timeout
|
||||||
|
if (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - lastPacketTime > 10000)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisconnectProtocol();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisconnectProtocol()
|
||||||
|
{
|
||||||
|
if (Server.Instance.Sessions.GetValueOrDefault(id) is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
c.Warn($"{id} disconnected");
|
||||||
|
client.Close();
|
||||||
|
Server.Instance.Sessions.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.Common", "AscNet.Com
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.SDKServer", "AscNet.SDKServer\AscNet.SDKServer.csproj", "{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AscNet.SDKServer", "AscNet.SDKServer\AscNet.SDKServer.csproj", "{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AscNet.GameServer", "AscNet.GameServer\AscNet.GameServer.csproj", "{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -27,6 +29,10 @@ Global
|
||||||
{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B5040F93-BA7F-4E76-AF54-E3FAA857A5DA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EB20C0CB-7CA1-459F-8410-7A27CC99F98C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AscNet.GameServer\AscNet.GameServer.csproj" />
|
||||||
<ProjectReference Include="..\AscNet.SDKServer\AscNet.SDKServer.csproj" />
|
<ProjectReference Include="..\AscNet.SDKServer\AscNet.SDKServer.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue