Remove hash check, and document packet format inbound and out
This commit is contained in:
parent
d1ff953717
commit
a126358c5f
4 changed files with 67 additions and 52 deletions
|
@ -1,3 +1,3 @@
|
|||
class Constants {
|
||||
static const VERSION = "1.2.082924+1625";
|
||||
static const VERSION = "1.2.082924+1846";
|
||||
}
|
||||
|
|
|
@ -14,6 +14,21 @@ import '../nbt/impl/StringTag.dart';
|
|||
class PacketServer {
|
||||
static ServerSocket? socket;
|
||||
static bool shouldRestart = true;
|
||||
|
||||
/// Packet Data Format:
|
||||
///
|
||||
/// 8 Bytes (Long) - Total expected bytes of packet minus the 8 bytes here.
|
||||
/// 8 bytes (Long) - Sequence ID
|
||||
/// 8 bytes (Long) - Number of bytes to read
|
||||
/// <arbitrary> - NBT Data
|
||||
///
|
||||
/// Response Format:
|
||||
///
|
||||
/// 8 bytes (Long) - Total expected bytes in packet minus the 8 bytes here.
|
||||
/// 1 byte - Success flag, Zero or 255 currently.
|
||||
/// 8 byes (Long) - Packet Length
|
||||
/// <arbitrary> - NBT Data
|
||||
///
|
||||
static Future<void> start(int port) async {
|
||||
socket = await ServerSocket.bind(InternetAddress.anyIPv4, port);
|
||||
print("Server now listening on port ${port}");
|
||||
|
@ -41,7 +56,6 @@ class PacketServer {
|
|||
layer.resetPosition();
|
||||
layer.readLong(); // This is unused outside of the above sanity check.
|
||||
try {
|
||||
List<int> dataHash = layer.readBytes(32); // Sha256
|
||||
int sequenceID = layer.readLong();
|
||||
print("Sequence ID in request: $sequenceID");
|
||||
|
||||
|
@ -49,53 +63,38 @@ class PacketServer {
|
|||
|
||||
List<int> remainingBytes = layer.readBytes(numBytes);
|
||||
|
||||
String sha256OriginalHash = Hashing.bytes2Hash(dataHash);
|
||||
String sha256Hash =
|
||||
Hashing.bytes2Hash(Hashing.sha1Sum(remainingBytes));
|
||||
if (sha256OriginalHash == sha256Hash) {
|
||||
CompoundTag tag = await NbtIo.readFromStream(
|
||||
Uint8List.fromList(remainingBytes));
|
||||
StringBuilder builder = StringBuilder();
|
||||
Tag.writeStringifiedNamedTag(tag, builder, 0);
|
||||
CompoundTag tag =
|
||||
await NbtIo.readFromStream(Uint8List.fromList(remainingBytes));
|
||||
StringBuilder builder = StringBuilder();
|
||||
Tag.writeStringifiedNamedTag(tag, builder, 0);
|
||||
|
||||
print("Request from client: \n${builder}");
|
||||
print("Request from client: \n${builder}");
|
||||
|
||||
C2SRequestPacket request = C2SRequestPacket();
|
||||
request.decodeTag(tag);
|
||||
C2SRequestPacket request = C2SRequestPacket();
|
||||
request.decodeTag(tag);
|
||||
|
||||
PacketResponse reply = await request.handleServerPacket();
|
||||
PacketResponse reply = await request.handleServerPacket();
|
||||
|
||||
// Server uses NBT to communicate
|
||||
builder = StringBuilder();
|
||||
Tag.writeStringifiedNamedTag(reply.replyDataTag, builder, 0);
|
||||
// Server uses NBT to communicate
|
||||
builder = StringBuilder();
|
||||
Tag.writeStringifiedNamedTag(reply.replyDataTag, builder, 0);
|
||||
|
||||
print("Response to client: \n${builder}");
|
||||
Uint8List nbtData = await NbtIo.writeToStream(reply.replyDataTag);
|
||||
print("Response to client: \n${builder}");
|
||||
Uint8List nbtData = await NbtIo.writeToStream(reply.replyDataTag);
|
||||
|
||||
layer.clear();
|
||||
layer.writeLong(sequenceID);
|
||||
layer.writeByte(0xFF); // Successful receipt
|
||||
layer.writeBytes(Hashing.sha256Sum(nbtData));
|
||||
layer.writeLong(nbtData.lengthInBytes);
|
||||
layer.writeBytes(nbtData);
|
||||
nbtData = layer.bytes;
|
||||
layer.clear();
|
||||
layer.writeLong(sequenceID);
|
||||
layer.writeByte(0xFF); // Successful receipt
|
||||
layer.writeLong(nbtData.lengthInBytes);
|
||||
layer.writeBytes(nbtData);
|
||||
nbtData = layer.bytes;
|
||||
|
||||
// NOTE: Added a length indicator because SocketServer is apparently... really really dumb in its impl, and has no way to know when all data has been received, so no special event. We just have to check for it based on this initial value.
|
||||
layer.clear();
|
||||
layer.writeLong(nbtData.lengthInBytes);
|
||||
layer.writeBytes(nbtData);
|
||||
// NOTE: Added a length indicator because SocketServer is apparently... really really dumb in its impl, and has no way to know when all data has been received, so no special event. We just have to check for it based on this initial value.
|
||||
layer.clear();
|
||||
layer.writeLong(nbtData.lengthInBytes);
|
||||
layer.writeBytes(nbtData);
|
||||
|
||||
sock.add(layer.bytes);
|
||||
} else {
|
||||
// Return a failure packet
|
||||
layer.clear();
|
||||
layer.writeLong(sequenceID);
|
||||
layer.writeByte(0x00);
|
||||
|
||||
sock.add(layer.bytes); // Failure code.
|
||||
print(
|
||||
"ERROR: The inbound hash did not match real hash: $sha256OriginalHash != $sha256Hash\n> REFUSING TO PROCESS PACKET. SENDING ERROR CODE TO CLIENT");
|
||||
}
|
||||
sock.add(layer.bytes);
|
||||
} catch (E, stack) {
|
||||
response.contents
|
||||
.put("error", StringTag.valueOf("Malformed request packet"));
|
||||
|
@ -145,6 +144,21 @@ class PacketClient {
|
|||
/// Tries to send a packet to the connected server
|
||||
///
|
||||
/// On success, returns either, the decoded [S2CResponse], or on error a S2CResponse containing an error and a stacktrace as [StringTag]
|
||||
///
|
||||
/// Packet Data Format:
|
||||
///
|
||||
/// 8 Bytes (Long) - Total expected bytes of packet minus the 8 bytes here.
|
||||
/// 8 bytes (Long) - Sequence ID
|
||||
/// 8 bytes (Long) - Number of bytes to read
|
||||
/// <arbitrary> - NBT Data
|
||||
///
|
||||
/// Response Format:
|
||||
///
|
||||
/// 8 bytes (Long) - Total expected bytes in packet minus the 8 bytes here.
|
||||
/// 1 byte - Success flag, Zero or 255 currently.
|
||||
/// 8 byes (Long) - Packet Length
|
||||
/// <arbitrary> - NBT Data
|
||||
///
|
||||
Future<S2CResponse> send(IPacket packet, bool shouldReconnect) async {
|
||||
if (!connected) {
|
||||
return S2CResponse();
|
||||
|
@ -158,14 +172,12 @@ class PacketClient {
|
|||
|
||||
Uint8List nbtData =
|
||||
await NbtIo.writeToStream(request.encodeTag().asCompoundTag());
|
||||
List<int> nbtDataHash = Hashing.sha256Sum(nbtData);
|
||||
|
||||
ByteLayer reply = ByteLayer();
|
||||
CompoundTag NBTTag = CompoundTag();
|
||||
|
||||
while (!success) {
|
||||
layer.clear();
|
||||
layer.writeBytes(nbtDataHash);
|
||||
layer.writeLong(packetSequence);
|
||||
layer.writeLong(nbtData.lengthInBytes);
|
||||
layer.writeBytes(nbtData);
|
||||
|
@ -196,15 +208,11 @@ class PacketClient {
|
|||
reply.readLong(); // This is unused outside of the sanity check above.
|
||||
int sequence = reply.readLong();
|
||||
int successReceipt = reply.readByte();
|
||||
List<int> serverHash = reply.readBytes(32);
|
||||
String srvHashStr = Hashing.bytes2Hash(serverHash);
|
||||
int numBytes = reply.readLong();
|
||||
List<int> pktBytes = reply.readBytes(numBytes);
|
||||
String pktHash = Hashing.bytes2Hash(Hashing.sha256Sum(pktBytes));
|
||||
|
||||
if (successReceipt == 0xFF &&
|
||||
packetSequence == sequence &&
|
||||
srvHashStr == pktHash) success = true;
|
||||
if (successReceipt == 0xFF && packetSequence == sequence)
|
||||
success = true;
|
||||
|
||||
if (success) {
|
||||
NBTTag = await NbtIo.readFromStream(Uint8List.fromList(pktBytes));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue