Skip to content

Instantly share code, notes, and snippets.

@Proximyst
Last active September 9, 2018 07:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Proximyst/1db53b4ee8bc7a5aa0a89488960029f1 to your computer and use it in GitHub Desktop.
Save Proximyst/1db53b4ee8bc7a5aa0a89488960029f1 to your computer and use it in GitHub Desktop.
/**
* Defines different encodings to use for packet handling.
*/
enum class PacketEncoding {
/**
* Handle the packet with no compression whatsoever.
*/
UNCOMPRESSED {
override fun decode(data : ByteBuf) : ByteBuf {
return data
}
override fun encode(data : ByteBuf) : ByteBuf {
return data
}
},
/**
* Conform to the compression format, but handle the packet with no compression.
* This is used when it doesn't hit the threshold for compression or when
* the incoming packet is 100% sure to not be compressed.
*/
UNCOMPRESSED_WITH_COMPRESSION_ENABLED {
override fun decode(data : ByteBuf) : ByteBuf {
VarInt.decode(data)
return data
}
override fun encode(data : ByteBuf) : ByteBuf {
val buf = 0.toVarInt().encode()
buf.writeBytes(data)
return buf
}
},
/**
* Handles the packet with ZLIB compression.
*
* The only time it handles it without compression is decoding packets
* which have an uncompressed length of 0.
*/
COMPRESSED {
override fun decode(data : ByteBuf) : ByteBuf {
val uncompressedLength = VarInt.decode(data)?.contained() ?: return Unpooled.buffer()
if (uncompressedLength == 0)
return data
val inflater = Inflater()
val byteArray = ByteArray(data.readableBytes())
data.readBytes(byteArray)
inflater.setInput(byteArray)
val result = ByteArray(uncompressedLength)
if (inflater.inflate(result) != uncompressedLength)
throw IllegalArgumentException("the uncompressed data is not correctly labelled")
return Unpooled.copiedBuffer(result)
}
override fun encode(data : ByteBuf) : ByteBuf {
val size = data.readableBytes()
val compressedData = ByteArrayOutputStream().also {
it.write(size)
DeflaterOutputStream(it).use {
val array = ByteArray(size)
data.readBytes(array)
it.write(array)
}
}.toByteArray()
val ret = compressedData.size.toVarInt().encode()
ret.writeBytes(compressedData)
return ret
}
},
;
/**
* Encodes the [data] together to a [ByteBuf] per the enum constant.
*
* @param data
* The data of the packet.
*
* @return
* The encoded [ByteBuf], which may be ZLIB compressed per the enum constant.
*/
abstract fun encode(data : ByteBuf) : ByteBuf
/**
* Decodes the [data] from the [ByteBuf] and returns its ID and data as [ByteBuf].
*
* @throws IllegalArgumentException
* If the uncompressed data is not correctly labelled, this is thrown.
*
* @param data
* The [ByteBuf] of the incoming packet. Its readableBytes will be modified.
*
* @return
* The [ByteBuf] of the ID and data of the enclosed packet.
*/
abstract fun decode(data : ByteBuf) : ByteBuf
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment