Skip to content

Commit

Permalink
Merge pull request #7 from zkhssb/new
Browse files Browse the repository at this point in the history
编码与连接优化
  • Loading branch information
zkhssb authored Jan 23, 2024
2 parents 7b2240c + ee5d74f commit cfd8e14
Show file tree
Hide file tree
Showing 32 changed files with 918 additions and 65 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore

# NectarRcon Config
config.json
servers.json
passwords.json

# User-specific files
*.rsuser
*.suo
Expand Down
26 changes: 20 additions & 6 deletions NectarRCON.Adapter.Minecraft/MinecraftRconClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using NectarRCON.Export.Client;
using NectarRCON.Export.Interfaces;
using System.ComponentModel;
using System.Text;

namespace NectarRCON.Adapter.Minecraft
{
Expand All @@ -11,8 +12,13 @@ public class MinecraftRconClient : BaseTcpClient, IRconAdapter
private static readonly int MaxMessageSize = 4110;

private readonly MemoryStream _buffer = new();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
private int lastId = 0;
private readonly SemaphoreSlim _semaphore = new(1);
private int _lastId;
/// <summary>
/// 编码
/// 默认编码 UTF8
/// </summary>
private new Encoding _encoding = Encoding.UTF8;

public void Disconnect()
{
Expand Down Expand Up @@ -56,6 +62,14 @@ public string Run(string command)
}
}

public Encoding GetEncoding()
=> _encoding;

public void SetEncoding(Encoding encoding)
{
_encoding = encoding;
}

public bool Connect(string address, int port)
{
_semaphore.Wait();
Expand All @@ -76,7 +90,7 @@ public bool Authenticate(string password)
try
{
Packet packet = Send(new Packet(PacketType.Authenticate, password));
return packet.Id == lastId;
return packet.Id == _lastId;
}
finally
{
Expand All @@ -86,9 +100,9 @@ public bool Authenticate(string password)

private Packet Send(Packet packet)
{
Interlocked.Increment(ref lastId);
packet.SetId(lastId);
return PacketEncoder.Decode(Send(packet.Encode()));
Interlocked.Increment(ref _lastId);
packet.SetId(_lastId);
return PacketEncoder.Decode(Send(packet.Encode(_encoding)), _encoding);
}
}
}
4 changes: 2 additions & 2 deletions NectarRCON.Adapter.Minecraft/Packet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ public void SetId(int id)
Id = id;
}

public byte[] Encode()
public byte[] Encode(Encoding? encoding = null)
{
List<byte> bytes = new List<byte>();
var data = Encoding.UTF8.GetBytes(Body);
var data = (encoding?? Encoding.UTF8).GetBytes(Body);
bytes.AddRange(BitConverter.GetBytes(PacketEncoder.HeaderLength + data.Length));
bytes.AddRange(BitConverter.GetBytes(Id));
bytes.AddRange(BitConverter.GetBytes((int)Type));
Expand Down
10 changes: 5 additions & 5 deletions NectarRCON.Adapter.Minecraft/PacketEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,24 @@ public enum PacketType : int
Authenticate // 3: Login
}

public class PacketEncoder
public abstract class PacketEncoder
{
public const int HeaderLength = 10;

public static byte[] Encode(Packet msg)
public static byte[] Encode(Packet msg, Encoding? encoding = null)
{
List<byte> bytes = new List<byte>();

bytes.AddRange(BitConverter.GetBytes(msg.Length));
bytes.AddRange(BitConverter.GetBytes(msg.Id));
bytes.AddRange(BitConverter.GetBytes((int)msg.Type));
bytes.AddRange(Encoding.UTF8.GetBytes(msg.Body));
bytes.AddRange((encoding??Encoding.UTF8).GetBytes(msg.Body));
bytes.AddRange(new byte[] { 0, 0 });

return bytes.ToArray();
}

public static Packet Decode(byte[] bytes)
public static Packet Decode(byte[] bytes, Encoding? encoding = null)
{
if (bytes.Length < HeaderLength) { throw new ArgumentException("packet length too short"); }
int len = BitConverter.ToInt32(bytes, 0);
Expand All @@ -37,7 +37,7 @@ public static Packet Decode(byte[] bytes)
string body = string.Empty;
if (bodyLen > 0)
{
body = Encoding.UTF8.GetString(bytes, 12, bodyLen);
body = (encoding??Encoding.UTF8).GetString(bytes, 12, bodyLen);
}
return new Packet(len, id, (PacketType)type, body);
}
Expand Down
7 changes: 6 additions & 1 deletion NectarRCON.Export/Interfaces/IRconAdapter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace NectarRCON.Export.Interfaces;
using System.Text;

namespace NectarRCON.Export.Interfaces;
/// <summary>
/// Rcon协议兼容接口
/// </summary>
Expand Down Expand Up @@ -30,4 +32,7 @@ public interface IRconAdapter : IDisposable
/// </summary>

string Run(string command);

Encoding GetEncoding();
void SetEncoding(Encoding encoding);
}
6 changes: 5 additions & 1 deletion NectarRCON.Export/NectarRCON.Export.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net7.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NectarRCON.Updater\NectarRCON.Updater.csproj" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions NectarRCON.Tests/NectarRCON.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
<ProjectReference Include="..\NectarRCON.Adapter.Minecraft\NectarRCON.Adapter.Minecraft.csproj" />
<ProjectReference Include="..\NectarRCON.Core\NectarRCON.Core.csproj" />
<ProjectReference Include="..\NectarRCON.Export\NectarRCON.Export.csproj" />
<ProjectReference Include="..\NectarRCON.Updater\NectarRCON.Updater.csproj" />
<ProjectReference Include="..\NectarRCON\NectarRCON.csproj" />
</ItemGroup>

Expand Down
40 changes: 40 additions & 0 deletions NectarRCON.Tests/UpdaterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using NectarRCON.Updater;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NectarRCON.Tests
{
[TestClass]
public class UpdaterTests
{
[TestMethod]
public void Github()
{
IUpdater updater = new GithubUpdater();
updater.SetVersion("NectarRcon-x86-1.0.0");
updater.IsLatestVersion();
}

[TestMethod]
public void AppVersionTest()
{
AppVersion versionA = AppVersion.ParseVersion("TestApp-x64-1.0.0-beta1");
AppVersion versionB = AppVersion.ParseVersion("TestApp-x64-1.0.0-beta2");

Assert.IsTrue(versionA.Equals(versionA));
Assert.IsFalse(versionA.Equals(versionB));

#pragma warning disable CS1718 // 对同一变量进行了比较
Assert.IsTrue(versionA == versionA);
Assert.IsFalse(versionA != versionA);
Assert.IsFalse(versionA > versionA);
#pragma warning restore CS1718 // 对同一变量进行了比较

Assert.IsTrue(versionB > versionA);
Assert.IsFalse(versionB < versionA);
}
}
}
105 changes: 105 additions & 0 deletions NectarRCON.Updater/AppVersion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;

namespace NectarRCON.Updater
{
public class AppVersion
{
public string AppName { get; set; } = string.Empty;
public int Version { get; set; }
public int Major { get;set; }
public int Minor { get;set; }
public int Patch { get;set; }
public int? Build { get; set; }
public string PreReleaseType { get; set; } = string.Empty;
public string Platform { get; set; } = string.Empty;
public bool IsPreRelease
=> !string.IsNullOrEmpty(PreReleaseType);

public override string ToString()
{
return $"{AppName}-{Platform}-{Major}.{Minor}.{Patch}" + (IsPreRelease ? $"-{PreReleaseType}{Build}" : string.Empty);
}

public override bool Equals(object? obj)
{
return obj?.ToString() == ToString();
}

public static bool operator <(AppVersion a, AppVersion b)
{
return a.Version < b.Version || (a.Build ?? 0) < (b.Build ?? 0);
}

public static bool operator >(AppVersion a, AppVersion b)
{
return a.Version > b.Version || (a.Build ?? 0) > (b.Build ?? 0);
}

public static bool operator ==(AppVersion a, AppVersion b)
{
return a.Version == b.Version && (a.Build ?? 0) == (b.Build ?? 0);
}

public static bool operator !=(AppVersion a, AppVersion b)
{
return a.Version != b.Version || (a.Build ?? 0) != (b.Build ?? 0);
}

private AppVersion() { }

public static AppVersion ParseVersion(string version)
{
string[] versionParts = version.Split("-");
if (versionParts.Length > 2)
{
AppVersion result = new();
string name = versionParts[0];
string platform = versionParts[1];
string ver = versionParts[2];
string preRelease = string.Empty;

if (versionParts.Length > 3)
{
preRelease = versionParts[3];
}

Regex versionRegex = new(@"(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)");
Match versionMatch = versionRegex.Match(ver);

if (versionMatch.Success)
{
result.Version = int.Parse(versionMatch.Groups["major"].Value + versionMatch.Groups["minor"].Value + versionMatch.Groups["patch"].Value);
result.Major = int.Parse(versionMatch.Groups["major"].Value);
result.Minor = int.Parse(versionMatch.Groups["minor"].Value);
result.Patch = int.Parse(versionMatch.Groups["patch"].Value);
}

Regex preReleaseRegex = new(@"(?<preRelease>[a-zA-Z]+)(?<build>\d+)");
Match preReleaseMatch = preReleaseRegex.Match(preRelease);

if (preReleaseMatch.Success)
{
if (preReleaseMatch.Groups["build"].Success)
{
result.Build = int.Parse(preReleaseMatch.Groups["build"].Value);
}
if (preReleaseMatch.Groups["preRelease"].Success)
{
result.PreReleaseType = preReleaseMatch.Groups["preRelease"].Value;
}
}

result.Platform = platform;
result.AppName = name;
return result;
}
throw new InvalidOperationException("Invalid version format");
}

public override int GetHashCode()
{
return RuntimeHelpers.GetHashCode(ToString());
}
}
}
Loading

0 comments on commit cfd8e14

Please sign in to comment.