2019-09-23 23:09:00 +02:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
using System.Net.Sockets;
|
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
|
|
|
|
namespace MinecraftClient.Protocol.Handlers
|
|
|
|
|
|
{
|
|
|
|
|
|
class PacketProxy
|
|
|
|
|
|
{
|
|
|
|
|
|
private int compression_treshold = 0;
|
|
|
|
|
|
private bool handshake_phase = true;
|
|
|
|
|
|
private bool login_phase = true;
|
|
|
|
|
|
TcpClient client;
|
|
|
|
|
|
TcpClient server;
|
|
|
|
|
|
|
|
|
|
|
|
public PacketProxy(TcpClient client, TcpClient server)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.client = client;
|
|
|
|
|
|
this.server = server;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Run()
|
|
|
|
|
|
{
|
|
|
|
|
|
Thread t = new Thread(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
do { Thread.Sleep(100); }
|
|
|
|
|
|
while (Update(true));
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (System.IO.IOException) { }
|
|
|
|
|
|
catch (SocketException) { }
|
|
|
|
|
|
catch (ObjectDisposedException) { }
|
|
|
|
|
|
});
|
|
|
|
|
|
t.Name = "UpdaterServer";
|
|
|
|
|
|
t.Start();
|
|
|
|
|
|
|
|
|
|
|
|
t = new Thread(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
do { Thread.Sleep(100); }
|
|
|
|
|
|
while (Update(false));
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (System.IO.IOException) { }
|
|
|
|
|
|
catch (SocketException) { }
|
|
|
|
|
|
catch (ObjectDisposedException) { }
|
|
|
|
|
|
});
|
|
|
|
|
|
t.Name = "UpdaterClient";
|
|
|
|
|
|
t.Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool Update(bool server)
|
|
|
|
|
|
{
|
|
|
|
|
|
TcpClient c = server ? this.server : this.client;
|
|
|
|
|
|
if (c.Client == null || !c.Connected) { return false; }
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
while (c.Client.Available > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
int packetID = 0;
|
|
|
|
|
|
byte[] packetData = new byte[] { };
|
|
|
|
|
|
byte[] packetRawData = new byte[] { };
|
|
|
|
|
|
readNextPacket(c, ref packetID, ref packetData, ref packetRawData);
|
|
|
|
|
|
handlePacket(packetID, (byte[])packetData.Clone(), server);
|
|
|
|
|
|
(server ? this.client : this.server).Client.Send(packetRawData);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (SocketException) { return false; }
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void readNextPacket(TcpClient c, ref int packetID, ref byte[] packetData, ref byte[] packetRawData)
|
|
|
|
|
|
{
|
|
|
|
|
|
int size = readNextVarIntRAW(c);
|
|
|
|
|
|
packetData = readDataRAW(c, size);
|
|
|
|
|
|
packetRawData = concatBytes(getVarInt(size), packetData);
|
|
|
|
|
|
|
|
|
|
|
|
if (compression_treshold > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
int size_uncompressed = readNextVarInt(ref packetData);
|
|
|
|
|
|
if (size_uncompressed != 0)
|
|
|
|
|
|
packetData = ZlibUtils.Decompress(packetData, size_uncompressed);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
packetID = readNextVarInt(ref packetData);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void handlePacket(int packetID, byte[] packetData, bool server)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Console.WriteLine((server ? "[S -> C] 0x" : "[C -> S] 0x") + packetID.ToString("x2"));
|
|
|
|
|
|
if (login_phase)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (server)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (packetID)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0x00:
|
|
|
|
|
|
Console.WriteLine("[S -> C] Login rejected");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x01:
|
|
|
|
|
|
Console.WriteLine("[S -> C] Encryption request");
|
|
|
|
|
|
Console.WriteLine(@"[WARNING] ENCRYPTION IS NOT SUPPORTED BY PROXY !!");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x02:
|
|
|
|
|
|
login_phase = false;
|
|
|
|
|
|
Console.WriteLine("[S -> C] Login successfull");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x03:
|
|
|
|
|
|
compression_treshold = readNextVarInt(ref packetData);
|
|
|
|
|
|
Console.WriteLine("[S -> C] Compression Treshold: " + compression_treshold);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (packetID)
|
|
|
|
|
|
{
|
|
|
|
|
|
case 0x00:
|
|
|
|
|
|
Console.WriteLine("[C -> S] " + (handshake_phase ? "Handshake" : "Login request"));
|
|
|
|
|
|
handshake_phase = false;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!server)
|
|
|
|
|
|
{
|
|
|
|
|
|
double x, y, z;
|
|
|
|
|
|
bool g;
|
|
|
|
|
|
switch (packetID)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Do debug work here
|
|
|
|
|
|
case 0x0C:
|
|
|
|
|
|
x = readNextDouble(ref packetData);
|
|
|
|
|
|
y = readNextDouble(ref packetData);
|
|
|
|
|
|
z = readNextDouble(ref packetData);
|
|
|
|
|
|
g = readNextBool(ref packetData);
|
|
|
|
|
|
Console.WriteLine("[C -> S] Location: " + x + ", " + y + ", " + z + ", " + g);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 0x0D:
|
|
|
|
|
|
x = readNextDouble(ref packetData);
|
|
|
|
|
|
y = readNextDouble(ref packetData);
|
|
|
|
|
|
z = readNextDouble(ref packetData);
|
|
|
|
|
|
readNextDouble(ref packetData); //skip 2 floats: look yaw & pitch
|
|
|
|
|
|
g = readNextBool(ref packetData);
|
|
|
|
|
|
Console.WriteLine("[C -> S] Location: " + x + ", " + y + ", " + z + ", (look)" + ", " + g);
|
|
|
|
|
|
break;
|
2020-03-29 18:41:26 +02:00
|
|
|
|
case 0x09:
|
|
|
|
|
|
byte window = readNextByte(ref packetData);
|
|
|
|
|
|
short slot = readNextShort(ref packetData);
|
|
|
|
|
|
byte button = readNextByte(ref packetData);
|
|
|
|
|
|
short action = readNextShort(ref packetData);
|
|
|
|
|
|
int mode = readNextVarInt(ref packetData);
|
|
|
|
|
|
bool slotPresent = readNextBool(ref packetData);
|
|
|
|
|
|
int itemId = -1;
|
|
|
|
|
|
byte itemCount = 0;
|
|
|
|
|
|
if (slotPresent)
|
|
|
|
|
|
{
|
|
|
|
|
|
itemId = readNextVarInt(ref packetData);
|
|
|
|
|
|
itemCount = readNextByte(ref packetData);
|
|
|
|
|
|
}
|
|
|
|
|
|
Console.WriteLine("[C -> S] Window #" + window + " click: #" + slot + " button " + button + " action " + action + " mode " + mode + " item " + itemId + " x" + itemCount);
|
|
|
|
|
|
break;
|
2019-09-23 23:09:00 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
client.Close();
|
|
|
|
|
|
server.Close();
|
|
|
|
|
|
}
|
|
|
|
|
|
catch { }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private byte[] readDataRAW(TcpClient c, int offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (offset > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] cache = new byte[offset];
|
|
|
|
|
|
Receive(c, cache, 0, offset, SocketFlags.None);
|
|
|
|
|
|
return cache;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (OutOfMemoryException) { }
|
|
|
|
|
|
}
|
|
|
|
|
|
return new byte[] { };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private byte[] readData(int offset, ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<byte> read = new List<byte>();
|
|
|
|
|
|
List<byte> list = new List<byte>(cache);
|
|
|
|
|
|
while (offset > 0 && list.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
read.Add(list[0]);
|
|
|
|
|
|
list.RemoveAt(0);
|
|
|
|
|
|
offset--;
|
|
|
|
|
|
}
|
|
|
|
|
|
cache = list.ToArray();
|
|
|
|
|
|
return read.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private string readNextString(ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
int length = readNextVarInt(ref cache);
|
|
|
|
|
|
if (length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Encoding.UTF8.GetString(readData(length, ref cache));
|
|
|
|
|
|
}
|
|
|
|
|
|
else return "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private bool readNextBool(ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] rawValue = readData(1, ref cache);
|
|
|
|
|
|
return rawValue[0] != 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-03-29 18:41:26 +02:00
|
|
|
|
private byte readNextByte(ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] rawValue = readData(1, ref cache);
|
|
|
|
|
|
return rawValue[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private short readNextShort(ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] rawValue = readData(2, ref cache);
|
|
|
|
|
|
Array.Reverse(rawValue); //Endianness
|
|
|
|
|
|
return BitConverter.ToInt16(rawValue, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2019-09-23 23:09:00 +02:00
|
|
|
|
private double readNextDouble(ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
byte[] rawValue = readData(8, ref cache);
|
|
|
|
|
|
Array.Reverse(rawValue); //Endianness
|
|
|
|
|
|
return BitConverter.ToDouble(rawValue, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int readNextVarIntRAW(TcpClient c)
|
|
|
|
|
|
{
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
int j = 0;
|
|
|
|
|
|
int k = 0;
|
|
|
|
|
|
byte[] tmp = new byte[1];
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
Receive(c, tmp, 0, 1, SocketFlags.None);
|
|
|
|
|
|
k = tmp[0];
|
|
|
|
|
|
i |= (k & 0x7F) << j++ * 7;
|
|
|
|
|
|
if (j > 5) throw new OverflowException("VarInt too big");
|
|
|
|
|
|
if ((k & 0x80) != 128) break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private int readNextVarInt(ref byte[] cache)
|
|
|
|
|
|
{
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
int j = 0;
|
|
|
|
|
|
int k = 0;
|
|
|
|
|
|
byte[] tmp = new byte[1];
|
|
|
|
|
|
while (true)
|
|
|
|
|
|
{
|
|
|
|
|
|
tmp = readData(1, ref cache);
|
|
|
|
|
|
k = tmp[0];
|
|
|
|
|
|
i |= (k & 0x7F) << j++ * 7;
|
|
|
|
|
|
if (j > 5) throw new OverflowException("VarInt too big");
|
|
|
|
|
|
if ((k & 0x80) != 128) break;
|
|
|
|
|
|
}
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static byte[] getVarInt(int paramInt)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<byte> bytes = new List<byte>();
|
|
|
|
|
|
while ((paramInt & -128) != 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
bytes.Add((byte)(paramInt & 127 | 128));
|
|
|
|
|
|
paramInt = (int)(((uint)paramInt) >> 7);
|
|
|
|
|
|
}
|
|
|
|
|
|
bytes.Add((byte)paramInt);
|
|
|
|
|
|
return bytes.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static byte[] concatBytes(params byte[][] bytes)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<byte> result = new List<byte>();
|
|
|
|
|
|
foreach (byte[] array in bytes)
|
|
|
|
|
|
result.AddRange(array);
|
|
|
|
|
|
return result.ToArray();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Receive(TcpClient c, byte[] buffer, int start, int offset, SocketFlags f)
|
|
|
|
|
|
{
|
|
|
|
|
|
int read = 0;
|
|
|
|
|
|
while (read < offset)
|
|
|
|
|
|
read += c.Client.Receive(buffer, start + read, offset - read, f);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|