mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
Packets refactoring to async
This commit is contained in:
parent
4d800a31fc
commit
5d03cd4fd1
10 changed files with 611 additions and 312 deletions
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Security.Cryptography;
|
||||
|
|
@ -476,6 +477,15 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
private async Task ReceiveAsync(byte[] buffer, int start, int offset, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (offset <= 0)
|
||||
return;
|
||||
|
||||
Stream stream = encrypted ? s! : c.GetStream();
|
||||
await stream.ReadExactlyAsync(buffer.AsMemory(start, offset), cancellationToken);
|
||||
}
|
||||
|
||||
private void Send(byte[] buffer)
|
||||
{
|
||||
if (encrypted)
|
||||
|
|
@ -484,7 +494,61 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
c.Client.Send(buffer);
|
||||
}
|
||||
|
||||
private bool Handshake(string uuid, string username, string sessionID, string host, int port, SessionToken session)
|
||||
private async Task SendAsync(byte[] buffer, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (buffer.Length == 0)
|
||||
return;
|
||||
|
||||
Stream stream = encrypted ? s! : c.GetStream();
|
||||
await stream.WriteAsync(buffer.AsMemory(0, buffer.Length), cancellationToken);
|
||||
await stream.FlushAsync(cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<byte[]> ReadDataAsync(int offset, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (offset <= 0)
|
||||
return [];
|
||||
|
||||
byte[] cache = new byte[offset];
|
||||
await ReceiveAsync(cache, 0, offset, cancellationToken);
|
||||
return cache;
|
||||
}
|
||||
|
||||
private async Task<string> ReadNextStringAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
ushort length = (ushort)await ReadNextShortAsync(cancellationToken);
|
||||
if (length <= 0)
|
||||
return "";
|
||||
|
||||
byte[] cache = new byte[length * 2];
|
||||
await ReceiveAsync(cache, 0, length * 2, cancellationToken);
|
||||
return Encoding.BigEndianUnicode.GetString(cache);
|
||||
}
|
||||
|
||||
private async Task<byte[]> ReadNextByteArrayAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
short len = await ReadNextShortAsync(cancellationToken);
|
||||
byte[] data = new byte[len];
|
||||
await ReceiveAsync(data, 0, len, cancellationToken);
|
||||
return data;
|
||||
}
|
||||
|
||||
private async Task<short> ReadNextShortAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
byte[] tmp = new byte[2];
|
||||
await ReceiveAsync(tmp, 0, 2, cancellationToken);
|
||||
Array.Reverse(tmp);
|
||||
return BitConverter.ToInt16(tmp, 0);
|
||||
}
|
||||
|
||||
private async Task<byte> ReadNextByteAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
byte[] result = new byte[1];
|
||||
await ReceiveAsync(result, 0, 1, cancellationToken);
|
||||
return result[0];
|
||||
}
|
||||
|
||||
private async Task<bool> HandshakeAsync(string uuid, string username, string sessionID, string host, int port, SessionToken session, CancellationToken cancellationToken = default)
|
||||
{
|
||||
//array
|
||||
byte[] data = new byte[10 + (username.Length + host.Length) * 2];
|
||||
|
|
@ -518,28 +582,28 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
Array.Reverse(sh);
|
||||
sh.CopyTo(data, 6 + (username.Length * 2) + (host.Length * 2));
|
||||
|
||||
Send(data);
|
||||
await SendAsync(data, cancellationToken);
|
||||
|
||||
byte[] pid = new byte[1];
|
||||
Receive(pid, 0, 1, SocketFlags.None);
|
||||
await ReceiveAsync(pid, 0, 1, cancellationToken);
|
||||
while (pid[0] == 0xFA) //Skip some early plugin messages
|
||||
{
|
||||
using (MainThreadExecutionScope.Enter(handler))
|
||||
ProcessPacket(pid[0]);
|
||||
Receive(pid, 0, 1, SocketFlags.None);
|
||||
await ReceiveAsync(pid, 0, 1, cancellationToken);
|
||||
}
|
||||
if (pid[0] == 0xFD)
|
||||
{
|
||||
string serverID = ReadNextString();
|
||||
byte[] PublicServerkey = ReadNextByteArray();
|
||||
byte[] token = ReadNextByteArray();
|
||||
string serverID = await ReadNextStringAsync(cancellationToken);
|
||||
byte[] PublicServerkey = await ReadNextByteArrayAsync(cancellationToken);
|
||||
byte[] token = await ReadNextByteArrayAsync(cancellationToken);
|
||||
|
||||
if (serverID == "-")
|
||||
ConsoleIO.WriteLineFormatted("§8" + Translations.mcc_server_offline, acceptnewlines: true);
|
||||
else if (Settings.Config.Logging.DebugMessages)
|
||||
ConsoleIO.WriteLineFormatted("§8" + string.Format(Translations.mcc_handshake, serverID));
|
||||
|
||||
return StartEncryption(uuid, username, sessionID, Config.Main.General.AccountType, token, serverID, PublicServerkey, session);
|
||||
return await StartEncryptionAsync(uuid, username, sessionID, Config.Main.General.AccountType, token, serverID, PublicServerkey, session, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -548,7 +612,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
private bool StartEncryption(string uuid, string username, string sessionID, LoginType type, byte[] token, string serverIDhash, byte[] serverPublicKey, SessionToken session)
|
||||
private async Task<bool> StartEncryptionAsync(string uuid, string username, string sessionID, LoginType type, byte[] token, string serverIDhash, byte[] serverPublicKey, SessionToken session, CancellationToken cancellationToken = default)
|
||||
{
|
||||
RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!;
|
||||
byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey();
|
||||
|
|
@ -571,7 +635,7 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
if (needCheckSession)
|
||||
{
|
||||
if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash, type))
|
||||
if (await ProtocolHandler.SessionCheckAsync(uuid, sessionID, serverHash, type))
|
||||
{
|
||||
session.ServerIDhash = serverIDhash;
|
||||
session.ServerPublicKey = serverPublicKey;
|
||||
|
|
@ -604,14 +668,14 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
token_enc.CopyTo(data, 5 + (short)key_enc.Length);
|
||||
|
||||
//Send it back
|
||||
Send(data);
|
||||
await SendAsync(data, cancellationToken);
|
||||
|
||||
//Getting the next packet
|
||||
byte[] pid = new byte[1];
|
||||
Receive(pid, 0, 1, SocketFlags.None);
|
||||
await ReceiveAsync(pid, 0, 1, cancellationToken);
|
||||
if (pid[0] == 0xFC)
|
||||
{
|
||||
ReadData(4);
|
||||
await ReadDataAsync(4, cancellationToken);
|
||||
s = new AesCfb8Stream(c.GetStream(), secretKey);
|
||||
encrypted = true;
|
||||
return true;
|
||||
|
|
@ -625,9 +689,14 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
public bool Login(PlayerKeyPair? playerKeyPair, SessionToken session, bool isTransfer = false)
|
||||
{
|
||||
if (Handshake(handler.GetUserUuidStr(), handler.GetUsername(), handler.GetSessionID(), handler.GetServerHost(), handler.GetServerPort(), session))
|
||||
return LoginAsync(playerKeyPair, session, isTransfer).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private async Task<bool> LoginAsync(PlayerKeyPair? playerKeyPair, SessionToken session, bool isTransfer = false)
|
||||
{
|
||||
if (await HandshakeAsync(handler.GetUserUuidStr(), handler.GetUsername(), handler.GetSessionID(), handler.GetServerHost(), handler.GetServerPort(), session))
|
||||
{
|
||||
Send(new byte[] { 0xCD, 0 });
|
||||
await SendAsync([0xCD, 0]);
|
||||
try
|
||||
{
|
||||
byte[] pid = new byte[1];
|
||||
|
|
@ -635,22 +704,24 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
{
|
||||
if (c.Connected)
|
||||
{
|
||||
Receive(pid, 0, 1, SocketFlags.None);
|
||||
await ReceiveAsync(pid, 0, 1);
|
||||
while (pid[0] >= 0xC0 && pid[0] != 0xFF) //Skip some early packets or plugin messages
|
||||
{
|
||||
using (MainThreadExecutionScope.Enter(handler))
|
||||
ProcessPacket(pid[0]);
|
||||
Receive(pid, 0, 1, SocketFlags.None);
|
||||
await ReceiveAsync(pid, 0, 1);
|
||||
}
|
||||
if (pid[0] == (byte)1)
|
||||
{
|
||||
ReadData(4); ReadNextString(); ReadData(5);
|
||||
await ReadDataAsync(4);
|
||||
_ = await ReadNextStringAsync();
|
||||
await ReadDataAsync(5);
|
||||
StartUpdating();
|
||||
return true; //The Server accepted the request
|
||||
}
|
||||
else if (pid[0] == (byte)0xFF)
|
||||
{
|
||||
string reason = ReadNextString();
|
||||
string reason = await ReadNextStringAsync();
|
||||
handler.OnConnectionLost(ChatBot.DisconnectReason.LoginRejected, reason);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue