package icu.samnyan.aqua.sega.aimedb import io.netty.buffer.ByteBuf import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.ByteToMessageDecoder import org.slf4j.LoggerFactory /** * A new decoder object will be created each time a new request comes in */ class AimeDbDecoder : ByteToMessageDecoder() { companion object { val logger = LoggerFactory.getLogger(AimeDbDecoder::class.java) } var length = 0 /** * Decrypt the incoming request including frame management * @param ctx ChannelHandlerContext * @param input ByteBuf in * @param out List */ override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList) { if (input.readableBytes() < 16) return if (length == 0) length = getLength(input) if (length < 0 || input.readableBytes() < length) return // Create a byte array to store the encrypted data val d = input.readBytes(length) val result = AimeDbEncryption.decrypt(d) d.release() val resultMap = mapOf( "type" to result.getShortLE(0x04).toInt(), "data" to result ) logger.debug("AimeDB Request Type: " + resultMap["type"]) out.add(resultMap) } /** * Get the length from request * * @param input the request * @return int the length of this request */ private fun getLength(input: ByteBuf): Int = try { val currentPos = input.readerIndex() val result = AimeDbEncryption.decrypt(input) // Check the header val header = result.getByte(0).toInt() assert(header == 0x3e) { "AimeDB: Invalid header $header" } // Read the length from offset 6 result.getShortLE(currentPos + 6).toInt() } catch (e: Exception) { logger.info("AimeDB: Invalid request received") logger.debug("AimeDB: Invalid request received: ${input.toString(Charsets.UTF_8)}") -1 } }