Skip to content

Commit 83c848f

Browse files
authored
Fix packet compression (fixes FTB Beyond, etc.). Closes #146 (#147)
Previously, the zlib compressor was initialized once, lazily, then reused for each packet by resetting the stream. This didn't properly emit the zlib headers, so packet compression was broken and caused "java.util.zip.DataFormatException: incorrect header check" on the server. Since packets are only compressed above a threshold, this problem manifested itself only on larger servers, such as 1.10.2 FTB Beyond and Skyfactory 3, and 1.12.2 SevTech: Ages, which require sending a large ModList above the compression threshold enabled by the server. Change to instead recreate the zlib compressor, each time it is used as to capture the full header. For symmetry, the decompressor is also recreated each time. * Removes self.compression_write and self.compression_read instance variables * Remove self.compression_write, initialize with cursor * Log compressing/decompressing packets in network debug mode
1 parent 2451e78 commit 83c848f

File tree

1 file changed

+13
-18
lines changed

1 file changed

+13
-18
lines changed

protocol/src/protocol/mod.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -972,8 +972,6 @@ pub struct Conn {
972972
cipher: Option<Aes128Cfb>,
973973

974974
compression_threshold: i32,
975-
compression_read: Option<ZlibDecoder<io::Cursor<Vec<u8>>>>,
976-
compression_write: Option<ZlibEncoder<io::Cursor<Vec<u8>>>>,
977975
}
978976

979977
impl Conn {
@@ -1000,8 +998,6 @@ impl Conn {
1000998
protocol_version,
1001999
cipher: Option::None,
10021000
compression_threshold: -1,
1003-
compression_read: Option::None,
1004-
compression_write: Option::None,
10051001
})
10061002
}
10071003

@@ -1016,16 +1012,18 @@ impl Conn {
10161012
0
10171013
};
10181014
if self.compression_threshold >= 0 && buf.len() as i32 > self.compression_threshold {
1019-
if self.compression_write.is_none() {
1020-
self.compression_write = Some(ZlibEncoder::new(io::Cursor::new(Vec::new()), Compression::default()));
1021-
}
10221015
extra = 0;
10231016
let uncompressed_size = buf.len();
10241017
let mut new = Vec::new();
10251018
VarInt(uncompressed_size as i32).write_to(&mut new)?;
1026-
let write = self.compression_write.as_mut().unwrap();
1027-
write.reset(io::Cursor::new(buf));
1019+
let mut write = ZlibEncoder::new(io::Cursor::new(buf), Compression::default());
10281020
write.read_to_end(&mut new)?;
1021+
let network_debug = unsafe { NETWORK_DEBUG };
1022+
if network_debug {
1023+
println!("Compressed for sending {} bytes to {} since > threshold {}, new={:?}",
1024+
uncompressed_size, new.len(), self.compression_threshold,
1025+
new);
1026+
}
10291027
buf = new;
10301028
}
10311029

@@ -1039,24 +1037,25 @@ impl Conn {
10391037
}
10401038

10411039
pub fn read_packet(&mut self) -> Result<packet::Packet, Error> {
1040+
let network_debug = unsafe { NETWORK_DEBUG };
10421041
let len = VarInt::read_from(self)?.0 as usize;
10431042
let mut ibuf = vec![0; len];
10441043
self.read_exact(&mut ibuf)?;
10451044

10461045
let mut buf = io::Cursor::new(ibuf);
10471046

10481047
if self.compression_threshold >= 0 {
1049-
if self.compression_read.is_none() {
1050-
self.compression_read = Some(ZlibDecoder::new(io::Cursor::new(Vec::new())));
1051-
}
10521048
let uncompressed_size = VarInt::read_from(&mut buf)?.0;
10531049
if uncompressed_size != 0 {
10541050
let mut new = Vec::with_capacity(uncompressed_size as usize);
10551051
{
1056-
let reader = self.compression_read.as_mut().unwrap();
1057-
reader.reset(buf);
1052+
let mut reader = ZlibDecoder::new(buf);
10581053
reader.read_to_end(&mut new)?;
10591054
}
1055+
if network_debug {
1056+
println!("Decompressed threshold={} len={} uncompressed_size={} to {} bytes",
1057+
self.compression_threshold, len, uncompressed_size, new.len());
1058+
}
10601059
buf = io::Cursor::new(new);
10611060
}
10621061
}
@@ -1067,8 +1066,6 @@ impl Conn {
10671066
Direction::Serverbound => Direction::Clientbound,
10681067
};
10691068

1070-
let network_debug = unsafe { NETWORK_DEBUG };
1071-
10721069
if network_debug {
10731070
println!("about to parse id={:x}, dir={:?} state={:?}", id, dir, self.state);
10741071
std::fs::File::create("last-packet")?.write_all(buf.get_ref())?;
@@ -1274,8 +1271,6 @@ impl Clone for Conn {
12741271
protocol_version: self.protocol_version,
12751272
cipher: Option::None,
12761273
compression_threshold: self.compression_threshold,
1277-
compression_read: Option::None,
1278-
compression_write: Option::None,
12791274
}
12801275
}
12811276
}

0 commit comments

Comments
 (0)