diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDBTypes.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDBTypes.kt new file mode 100644 index 00000000..5c5e3d59 --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDBTypes.kt @@ -0,0 +1 @@ +package icu.samnyan.aqua.sega.aimedb diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbDecoder.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbDecoder.kt index f423815c..45609444 100644 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbDecoder.kt +++ b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbDecoder.kt @@ -1,6 +1,5 @@ package icu.samnyan.aqua.sega.aimedb -import icu.samnyan.aqua.sega.aimedb.exception.InvalidRequestException import icu.samnyan.aqua.sega.aimedb.util.Encryption import io.netty.buffer.ByteBuf import io.netty.channel.ChannelHandlerContext @@ -25,7 +24,7 @@ class AimeDbDecoder : ByteToMessageDecoder() { * @param ctx ChannelHandlerContext * @param input ByteBuf in * @param out List - */ + */ @Throws(Exception::class) override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList) { if (input.readableBytes() < 16) return diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbRequestHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbRequestHandler.java deleted file mode 100644 index 26610765..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbRequestHandler.java +++ /dev/null @@ -1,96 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb; - -import icu.samnyan.aqua.sega.aimedb.handler.impl.*; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import lombok.AllArgsConstructor; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ - -@Component -@Scope("prototype") -@AllArgsConstructor -public class AimeDbRequestHandler extends ChannelInboundHandlerAdapter { - - private static final Logger logger = LoggerFactory.getLogger(AimeDbRequestHandler.class); - - private final CampaignHandler campaignHandler; - private final FeliCaLookupHandler feliCaLookupHandler; - private final FeliCaLookup2Handler feliCaLookup2Handler; - private final GoodbyeHandler goodbyeHandler; - private final HelloHandler helloHandler; - private final LogHandler logHandler; - private final LookupHandler lookupHandler; - private final Lookup2Handler lookup2Handler; - private final RegisterHandler registerHandler; - private final Unknown19Handler unknown19Handler; - private final TouchHandler touchHandler; - - - @Override - public void channelRead(@NotNull ChannelHandlerContext ctx, @NotNull Object msg) throws Exception { - if (msg instanceof Map) { - int type = ((int) ((Map) msg).get("type")); - ByteBuf data = (ByteBuf) ((Map) msg).get("data"); - switch (type) { - case 0x0001: - feliCaLookupHandler.handle(ctx, data); - break; - case 0x0004: - lookupHandler.handle(ctx, data); - break; - case 0x0005: - registerHandler.handle(ctx, data); - break; - case 0x0009: - logHandler.handle(ctx, data); - break; - case 0x000b: - campaignHandler.handle(ctx, data); - break; - case 0x000d: - touchHandler.handle(ctx, data); - break; - case 0x000f: - lookup2Handler.handle(ctx, data); - break; - case 0x0011: - feliCaLookup2Handler.handle(ctx, data); - break; - case 0x0013: - unknown19Handler.handle(ctx, data); - break; - case 0x0064: - helloHandler.handle(ctx, data); - break; - case 0x0066: - goodbyeHandler.handle(ctx, data); - break; - } - } - - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - logger.error("Error in AimeDB", cause); - ctx.close(); - } - - @Override - public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception { - super.channelInactive(ctx); - logger.debug("Connection closed"); - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbRequestHandler.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbRequestHandler.kt new file mode 100644 index 00000000..42fa866c --- /dev/null +++ b/src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbRequestHandler.kt @@ -0,0 +1,231 @@ +package icu.samnyan.aqua.sega.aimedb + +import icu.samnyan.aqua.sega.general.model.Card +import icu.samnyan.aqua.sega.general.service.CardService +import io.netty.buffer.ByteBuf +import io.netty.buffer.ByteBufUtil +import io.netty.buffer.Unpooled +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.ChannelInboundHandlerAdapter +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.context.annotation.Scope +import org.springframework.stereotype.Component +import java.nio.charset.StandardCharsets +import kotlin.jvm.optionals.getOrNull + +/** + * @author samnyan (privateamusement@protonmail.com) + */ +@Component +@Scope("prototype") +class AimeDbRequestHandler( + val cardService: CardService +): ChannelInboundHandlerAdapter() { + val logger: Logger = LoggerFactory.getLogger(AimeDbRequestHandler::class.java) + + data class AimeBaseInfo(val gameId: String, val keychipId: String) + + fun getBaseInfo(input: ByteBuf) = AimeBaseInfo( + gameId = input.toString(0x000a, 0x000e - 0x000a, StandardCharsets.US_ASCII), + keychipId = input.toString(0x0014, 0x001f - 0x0014, StandardCharsets.US_ASCII) + ) + + final val handlers = mapOf ByteBuf?>( + 0x0001 to ::doFelicaLookup, + 0x0004 to ::doLookup, + 0x0005 to ::doRegister, + 0x0009 to ::doLog, + 0x000b to ::doCampaign, + 0x000d to ::doTouch, + 0x000f to ::doLookup2, + 0x0011 to ::doFelicaLookup2, + 0x0013 to ::doUnknown19, + 0x0064 to ::doHello, + 0x0066 to ::doGoodbye + ) + + /** + * Handle the incoming request + */ + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is Map<*, *>) { + val type = msg["type"] as Int + val data = msg["data"] as ByteBuf + val base = getBaseInfo(data) + val handler = handlers[type] ?: let { + logger.error("AimeDB: Unknown request type: ${type.toString(16)}") + ctx.flush() + return + } + + logger.info("AimeDB: Request $handler for game ${base.gameId}, from keychip ${base.keychipId}") + + val result = handler(data) + if (result != null) ctx.writeAndFlush(result) + else ctx.flush() + } + } + + @Deprecated("Deprecated in Netty 5") // TODO: Move this to ChannelInboundHandler + override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) { + logger.error("AimeDB: Error", cause) + ctx.close() + } + + override fun channelInactive(ctx: ChannelHandlerContext) { + super.channelInactive(ctx) + logger.debug("AimeDB: Connection closed") + } + + /** + * Felica Lookup v1: Return the Felica IDm as-is + */ + fun doFelicaLookup(msg: ByteBuf): ByteBuf { + val idm = msg.slice(0x0020, 0x0028 - 0x0020).getLong(0) + val pmm = msg.slice(0x0028, 0x0030 - 0x0028).getLong(0) + logger.info("> Felica Lookup v1 ($idm, $pmm)") + + // Get the decimal represent of the hex value, same from minime + val accessCode = idm.toString().replace("-", "").padStart(20, '0') + + logger.info("> Response: $accessCode") + return Unpooled.copiedBuffer(ByteArray(0x0030)).apply { + setShortLE(0x0004, 0x0003) + setShortLE(0x0008, 1) + setBytes(0x0024, ByteBufUtil.decodeHexDump(accessCode)) + } + } + + /** + * Felica Lookup v2: Look up the card in the card repository, return the External ID + */ + fun doFelicaLookup2(msg: ByteBuf): ByteBuf { + val idm = msg.slice(0x0020, 0x0028 - 0x0020).getLong(0) + val pmm = msg.slice(0x0028, 0x0030 - 0x0028).getLong(0) + logger.info("> Felica Lookup v2 ($idm, $pmm)") + + // Get the decimal represent of the hex value, same from minime + val accessCode = idm.toString().replace("-", "").padStart(20, '0') + val aimeId = cardService.getCardByAccessCode(accessCode).getOrNull()?.extId ?: -1 + + logger.info("Response: $accessCode, $aimeId") + return Unpooled.copiedBuffer(ByteArray(0x0140)).apply { + setShortLE(0x0004, 0x0012) + setShortLE(0x0008, 1) + setLongLE(0x0020, aimeId) + setIntLE(0x0024, -0x1) // 0xFFFFFFFF + setIntLE(0x0028, -0x1) // 0xFFFFFFFF + setBytes(0x002c, ByteBufUtil.decodeHexDump(accessCode)) + setShortLE(0x0037, 0x0001) + } + } + + /** + * Lookup v1: Find the LUID in the database and return the External ID + */ + fun doLookup(msg: ByteBuf): ByteBuf { + val luid = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020)) + logger.info("> Lookup v1 ($luid)") + + val aimeId = cardService.getCardByAccessCode(luid).getOrNull()?.extId ?: -1 + + logger.info("> Response: $aimeId") + return Unpooled.copiedBuffer(ByteArray(0x0130)).apply { + setShortLE(0x0004, 0x0006) + setShortLE(0x0008, 1) + setLongLE(0x0020, aimeId) + setByte(0x0024, 0) + } + } + + fun doLookup2(msg: ByteBuf): ByteBuf { + val luid = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020)) + logger.info("> Lookup v2 ($luid)") + + val aimeId = cardService.getCardByAccessCode(luid).getOrNull()?.extId ?: -1 + + logger.info("Response: $aimeId") + return Unpooled.copiedBuffer(ByteArray(0x0130)).apply { + setShortLE(0x0004, 0x0010) + setShortLE(0x0008, 1) + setLongLE(0x0020, aimeId) + setByte(0x0024, 0) + } + } + + /** + * Register: Register a new card by access code + */ + fun doRegister(msg: ByteBuf): ByteBuf { + val luid = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020)) + logger.info("> Register ($luid)") + + var status = 0 + var aimeId = 0L + + if (cardService.getCardByAccessCode(luid).isEmpty) { + val card: Card = cardService.registerByAccessCode(luid) + + status = 1 + aimeId = card.extId + } + else logger.warn("> Duplicated Aime Card Register detected, access code: $luid") + + logger.info("> Response: $status, $aimeId") + return Unpooled.copiedBuffer(ByteArray(0x0030)).apply { + setShortLE(0x0004, 0x0006) + setShortLE(0x0008, status) + setLongLE(0x0020, aimeId) + } + } + + /** + * Log: Just log the request and return a status 1 + */ + fun doLog(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0020)).apply { + setShortLE(0x0004, 0x000a) + setShortLE(0x0008, 1) + } + + /** + * Campaign: Just return a status 1 + */ + fun doCampaign(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0200)).apply { + setShortLE(0x0004, 0x000c) + setShortLE(0x0008, 1) + } + + /** + * Touch: Just return a status 1 + */ + fun doTouch(msg: ByteBuf): ByteBuf { + val aimeId = msg.getUnsignedIntLE(0x0020) + logger.info("> Touch ($aimeId)") + + return Unpooled.copiedBuffer(ByteArray(0x0050)).apply { + setShortLE(0x0004, 0x000e) + setShortLE(0x0008, 1) + setShortLE(0x0020, 0x006f) + setShortLE(0x0024, 0x0001) + } + } + + /** + * We don't know what this is, just return a status 1 + */ + fun doUnknown19(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0040)).apply { + setShortLE(0x0004, 0x0014) + setShortLE(0x0008, 1) + } + + /** + * Ping: Just return a status 1 + */ + fun doHello(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0020)).apply { + setShortLE(0x0004, 0x0065) + setShortLE(0x0008, 1) + } + + fun doGoodbye(msg: ByteBuf) = null +} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/exception/InvalidRequestException.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/InvalidRequestException.java similarity index 71% rename from src/main/java/icu/samnyan/aqua/sega/aimedb/exception/InvalidRequestException.java rename to src/main/java/icu/samnyan/aqua/sega/aimedb/InvalidRequestException.java index 945e4a4a..43669e2b 100644 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/exception/InvalidRequestException.java +++ b/src/main/java/icu/samnyan/aqua/sega/aimedb/InvalidRequestException.java @@ -1,4 +1,4 @@ -package icu.samnyan.aqua.sega.aimedb.exception; +package icu.samnyan.aqua.sega.aimedb; /** * @author samnyan (privateamusement@protonmail.com) diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/BaseHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/BaseHandler.java deleted file mode 100644 index 4e9580b2..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/BaseHandler.java +++ /dev/null @@ -1,13 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler; - -import com.fasterxml.jackson.core.JsonProcessingException; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -public interface BaseHandler { - - void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException; -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/CampaignHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/CampaignHandler.java deleted file mode 100644 index ce93ca18..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/CampaignHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil; -import icu.samnyan.aqua.sega.aimedb.util.LogMapper; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class CampaignHandler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(CampaignHandler.class); - - private final LogMapper logMapper; - - @Autowired - public CampaignHandler(LogMapper logMapper) { - this.logMapper = logMapper; - } - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = AimeDbUtil.getBaseInfo(msg); - requestMap.put("type", "campaign"); - - - logger.info("Request: " + logMapper.write(requestMap)); - - Map resultMap = new HashMap<>(); - resultMap.put("type", "campaign"); - resultMap.put("status", 1); - - logger.info("Response: " + logMapper.write(resultMap)); - - ByteBuf respSrc = Unpooled.copiedBuffer(new byte[0x0200]); - respSrc.setShortLE(0x0004, 0x000c); - respSrc.setShortLE(0x0008, (int) resultMap.get("status")); - - ctx.writeAndFlush(respSrc); - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/FeliCaLookup2Handler.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/FeliCaLookup2Handler.kt deleted file mode 100644 index 6f3ff183..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/FeliCaLookup2Handler.kt +++ /dev/null @@ -1,57 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl - -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil -import icu.samnyan.aqua.sega.aimedb.util.LogMapper -import icu.samnyan.aqua.sega.general.dao.CardRepository -import io.netty.buffer.ByteBuf -import io.netty.buffer.ByteBufUtil -import io.netty.buffer.Unpooled -import io.netty.channel.ChannelHandlerContext -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Component - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -class FeliCaLookup2Handler( - val logMapper: LogMapper, - val cardRepository: CardRepository -) : BaseHandler { - val logger: Logger = LoggerFactory.getLogger(FeliCaLookup2Handler::class.java) - - override fun handle(ctx: ChannelHandlerContext, msg: ByteBuf) { - val requestMap = AimeDbUtil.getBaseInfo(msg) - requestMap["type"] = "felica_lookup2" - requestMap["idm"] = msg.slice(0x0030, 0x0038 - 0x0030) - requestMap["pmm"] = msg.slice(0x0038, 0x0040 - 0x0038) - - logger.info("Request: " + logMapper.write(requestMap)) - - // Get the decimal represent of the hex value, same from minime - val accessCode = (requestMap["idm"] as ByteBuf).getLong(0).toString() - .replace("-", "") // Prevent negative overflow - .padStart(20, '0') - - var aimeId: Long = -1 - val card = cardRepository.findByLuid(accessCode) - if (card.isPresent) { - aimeId = card.get().extId - } - - logger.info("Response: $accessCode, $aimeId") - - val respSrc = Unpooled.copiedBuffer(ByteArray(0x0140)) - respSrc.setShortLE(0x0004, 0x0012) - respSrc.setShortLE(0x0008, 1) - respSrc.setLongLE(0x0020, aimeId) - respSrc.setIntLE(0x0024, -0x1) - respSrc.setIntLE(0x0028, -0x1) - respSrc.setBytes(0x002c, ByteBufUtil.decodeHexDump(accessCode)) - respSrc.setShortLE(0x0037, 0x0001) - - ctx.writeAndFlush(respSrc) - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/FeliCaLookupHandler.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/FeliCaLookupHandler.kt deleted file mode 100644 index 7edc9556..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/FeliCaLookupHandler.kt +++ /dev/null @@ -1,44 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl - -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil -import icu.samnyan.aqua.sega.aimedb.util.LogMapper -import io.netty.buffer.ByteBuf -import io.netty.buffer.ByteBufUtil -import io.netty.buffer.Unpooled -import io.netty.channel.ChannelHandlerContext -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Component - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -class FeliCaLookupHandler(val logMapper: LogMapper) : BaseHandler { - val logger: Logger = LoggerFactory.getLogger(FeliCaLookupHandler::class.java) - - override fun handle(ctx: ChannelHandlerContext, msg: ByteBuf) { - val requestMap = AimeDbUtil.getBaseInfo(msg) - requestMap["type"] = "felica_lookup" - requestMap["idm"] = msg.slice(0x0020, 0x0028 - 0x0020) - requestMap["pmm"] = msg.slice(0x0028, 0x0030 - 0x0028) - - logger.info("Request: " + logMapper.write(requestMap)) - - - // Get the decimal represent of the hex value, same from minime - val accessCode = (requestMap["idm"] as ByteBuf).getLong(0).toString() - .replace("-", "") // Prevent negative overflow - .padStart(20, '0') - - logger.info("Response: $accessCode") - - val respSrc = Unpooled.copiedBuffer(ByteArray(0x0030)) - respSrc.setShortLE(0x0004, 0x0003) - respSrc.setShortLE(0x0008, 1) - respSrc.setBytes(0x0024, ByteBufUtil.decodeHexDump(accessCode)) - - ctx.writeAndFlush(respSrc) - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/GoodbyeHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/GoodbyeHandler.java deleted file mode 100644 index 6a2ea4a4..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/GoodbyeHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class GoodbyeHandler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(GoodbyeHandler.class); - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = new HashMap<>(); - requestMap.put("type", "goodbye"); - - - logger.info("Request: " + new ObjectMapper().writeValueAsString(requestMap)); - ctx.flush(); - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/HelloHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/HelloHandler.java deleted file mode 100644 index 3411ebe1..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/HelloHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil; -import icu.samnyan.aqua.sega.aimedb.util.LogMapper; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class HelloHandler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(HelloHandler.class); - - private final LogMapper logMapper; - - @Autowired - public HelloHandler(LogMapper logMapper) { - this.logMapper = logMapper; - } - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = AimeDbUtil.getBaseInfo(msg); - requestMap.put("type", "hello"); - - - logger.info("Request: " + logMapper.write(requestMap)); - - Map resultMap = new HashMap<>(); - resultMap.put("type", "hello"); - resultMap.put("status", 1); - - logger.info("Response: " + logMapper.write(resultMap)); - - ByteBuf respSrc = Unpooled.copiedBuffer(new byte[0x0020]); - respSrc.setShortLE(0x0004, 0x0065); - respSrc.setShortLE(0x0008, (int) resultMap.get("status")); - - ctx.writeAndFlush(respSrc); - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/LogHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/LogHandler.java deleted file mode 100644 index a248d1b2..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/LogHandler.java +++ /dev/null @@ -1,54 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil; -import icu.samnyan.aqua.sega.aimedb.util.LogMapper; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class LogHandler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(LogHandler.class); - - private final LogMapper logMapper; - - @Autowired - public LogHandler(LogMapper logMapper) { - this.logMapper = logMapper; - } - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = AimeDbUtil.getBaseInfo(msg); - requestMap.put("type", "log"); - - - logger.info("Request: " + logMapper.write(requestMap)); - - Map resultMap = new HashMap<>(); - resultMap.put("type", "log"); - resultMap.put("status", 1); - - logger.info("Response: " + logMapper.write(resultMap)); - - ByteBuf respSrc = Unpooled.copiedBuffer(new byte[0x0020]); - respSrc.setShortLE(0x0004, 0x000a); - respSrc.setShortLE(0x0008, (int) resultMap.get("status")); - - ctx.writeAndFlush(respSrc); - - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/Lookup2Handler.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/Lookup2Handler.kt deleted file mode 100644 index f49b6ec7..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/Lookup2Handler.kt +++ /dev/null @@ -1,48 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl - -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil.getBaseInfo -import icu.samnyan.aqua.sega.aimedb.util.LogMapper -import icu.samnyan.aqua.sega.general.dao.CardRepository -import io.netty.buffer.ByteBuf -import io.netty.buffer.ByteBufUtil -import io.netty.buffer.Unpooled -import io.netty.channel.ChannelHandlerContext -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Component - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -class Lookup2Handler( - val logMapper: LogMapper, - val cardRepository: CardRepository -) : BaseHandler { - val logger: Logger = LoggerFactory.getLogger(Lookup2Handler::class.java) - - override fun handle(ctx: ChannelHandlerContext, msg: ByteBuf) { - val requestMap = getBaseInfo(msg) - requestMap["type"] = "lookup2" - requestMap["luid"] = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020)) - - logger.info("Request: " + logMapper.write(requestMap)) - - var aimeId: Long = -1 - val card = cardRepository.findByLuid(requestMap["luid"] as String?) - if (card.isPresent) { - aimeId = card.get().extId - } - - logger.info("Response: $aimeId") - - val respSrc = Unpooled.copiedBuffer(ByteArray(0x0130)) - respSrc.setShortLE(0x0004, 0x0010) - respSrc.setShortLE(0x0008, 1) - respSrc.setLongLE(0x0020, aimeId) - respSrc.setByte(0x0024, 0) - - ctx.writeAndFlush(respSrc) - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/LookupHandler.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/LookupHandler.kt deleted file mode 100644 index 3bc74b40..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/LookupHandler.kt +++ /dev/null @@ -1,50 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl - -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil.getBaseInfo -import icu.samnyan.aqua.sega.aimedb.util.LogMapper -import icu.samnyan.aqua.sega.general.dao.CardRepository -import io.netty.buffer.ByteBuf -import io.netty.buffer.ByteBufUtil -import io.netty.buffer.Unpooled -import io.netty.channel.ChannelHandlerContext -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.stereotype.Component - -/** - * Mifare Card lookup? idk - * - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -class LookupHandler( - val logMapper: LogMapper, - val cardRepository: CardRepository -) : BaseHandler { - val logger: Logger = LoggerFactory.getLogger(LookupHandler::class.java) - - override fun handle(ctx: ChannelHandlerContext, msg: ByteBuf) { - val requestMap = getBaseInfo(msg) - requestMap["type"] = "lookup" - requestMap["luid"] = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020)) - - logger.info("Request: " + logMapper.write(requestMap)) - - var aimeId: Long = -1 - val card = cardRepository.findByLuid(requestMap["luid"] as String?) - if (card.isPresent) { - aimeId = card.get().extId - } - - logger.info("Response: $aimeId") - - val respSrc = Unpooled.copiedBuffer(ByteArray(0x0130)) - respSrc.setShortLE(0x0004, 0x0006) - respSrc.setShortLE(0x0008, 1) - respSrc.setLongLE(0x0020, aimeId) - respSrc.setByte(0x0024, 0) - - ctx.writeAndFlush(respSrc) - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/RegisterHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/RegisterHandler.java deleted file mode 100644 index 38120321..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/RegisterHandler.java +++ /dev/null @@ -1,71 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil; -import icu.samnyan.aqua.sega.aimedb.util.LogMapper; -import icu.samnyan.aqua.sega.general.model.Card; -import icu.samnyan.aqua.sega.general.service.CardService; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufUtil; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class RegisterHandler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(RegisterHandler.class); - - private final LogMapper logMapper; - - private final CardService cardService; - - @Autowired - public RegisterHandler(LogMapper logMapper, CardService cardService) { - this.logMapper = logMapper; - this.cardService = cardService; - } - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = AimeDbUtil.getBaseInfo(msg); - requestMap.put("type", "register"); - requestMap.put("luid", ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020))); - - logger.info("Request: " + logMapper.write(requestMap)); - - Map resultMap = new HashMap<>(); - resultMap.put("type", "register"); - - if (cardService.getCardByAccessCode((String) requestMap.get("luid")).isEmpty()) { - Card card = cardService.registerByAccessCode((String) requestMap.get("luid")); - - resultMap.put("status", 1); - resultMap.put("aimeId", card.getExtId()); - } else { - logger.warn("Duplicated Aime Card Register detected, access code: {}", requestMap.get("luid")); - resultMap.put("status", 0); - resultMap.put("aimeId", 0L); - } - - logger.info("Response: " + logMapper.write(resultMap)); - - ByteBuf respSrc = Unpooled.copiedBuffer(new byte[0x0030]); - respSrc.setShortLE(0x0004, 0x0006); - respSrc.setShortLE(0x0008, (int) resultMap.get("status")); - respSrc.setLongLE(0x0020, (long) resultMap.get("aimeId")); - - ctx.writeAndFlush(respSrc); - - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/TouchHandler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/TouchHandler.java deleted file mode 100644 index 9b8d4030..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/TouchHandler.java +++ /dev/null @@ -1,56 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil; -import icu.samnyan.aqua.sega.aimedb.util.LogMapper; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class TouchHandler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(TouchHandler.class); - - private final LogMapper logMapper; - - @Autowired - public TouchHandler(LogMapper logMapper) { - this.logMapper = logMapper; - } - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = AimeDbUtil.getBaseInfo(msg); - requestMap.put("type", "touch"); - requestMap.put("aimeId", msg.getUnsignedIntLE(0x0020)); - - logger.info("Request: " + logMapper.write(requestMap)); - - Map resultMap = new HashMap<>(); - resultMap.put("type", "touch"); - resultMap.put("status", 1); - - logger.info("Response: " + logMapper.write(resultMap)); - - ByteBuf respSrc = Unpooled.copiedBuffer(new byte[0x0050]); - respSrc.setShortLE(0x0004, 0x000e); - respSrc.setShortLE(0x0008, (int) resultMap.get("status")); - respSrc.setShortLE(0x0020, 0x006f); - respSrc.setShortLE(0x0024, 0x0001); - - ctx.writeAndFlush(respSrc); - - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/Unknown19Handler.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/Unknown19Handler.java deleted file mode 100644 index 58396d00..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/handler/impl/Unknown19Handler.java +++ /dev/null @@ -1,52 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.handler.impl; - -import com.fasterxml.jackson.core.JsonProcessingException; -import icu.samnyan.aqua.sega.aimedb.handler.BaseHandler; -import icu.samnyan.aqua.sega.aimedb.util.AimeDbUtil; -import icu.samnyan.aqua.sega.aimedb.util.LogMapper; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelHandlerContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class Unknown19Handler implements BaseHandler { - - private static final Logger logger = LoggerFactory.getLogger(Unknown19Handler.class); - - private final LogMapper logMapper; - - @Autowired - public Unknown19Handler(LogMapper logMapper) { - this.logMapper = logMapper; - } - - @Override - public void handle(ChannelHandlerContext ctx, ByteBuf msg) throws JsonProcessingException { - Map requestMap = AimeDbUtil.getBaseInfo(msg); - requestMap.put("type", "unknown19"); - - logger.info("Request: " + logMapper.write(requestMap)); - - Map resultMap = new HashMap<>(); - resultMap.put("type", "unknown19"); - resultMap.put("status", 1); - - logger.info("Response: " + logMapper.write(resultMap)); - - ByteBuf respSrc = Unpooled.copiedBuffer(new byte[0x0040]); - respSrc.setShortLE(0x0004, 0x0014); - respSrc.setShortLE(0x0008, (int) resultMap.get("status")); - - ctx.writeAndFlush(respSrc); - } -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/util/AimeDbUtil.kt b/src/main/java/icu/samnyan/aqua/sega/aimedb/util/AimeDbUtil.kt deleted file mode 100644 index 6fd5bd94..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/util/AimeDbUtil.kt +++ /dev/null @@ -1,15 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.util - -import io.netty.buffer.ByteBuf -import java.nio.charset.StandardCharsets - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -object AimeDbUtil { - @JvmStatic - fun getBaseInfo(input: ByteBuf) = mutableMapOf( - "gameId" to input.toString(0x000a, 0x000e - 0x000a, StandardCharsets.US_ASCII), - "keychipId" to input.toString(0x0014, 0x001f - 0x0014, StandardCharsets.US_ASCII) - ) -} diff --git a/src/main/java/icu/samnyan/aqua/sega/aimedb/util/LogMapper.java b/src/main/java/icu/samnyan/aqua/sega/aimedb/util/LogMapper.java deleted file mode 100644 index f2a3574f..00000000 --- a/src/main/java/icu/samnyan/aqua/sega/aimedb/util/LogMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package icu.samnyan.aqua.sega.aimedb.util; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import icu.samnyan.aqua.sega.util.jackson.ByteBufSerializer; -import io.netty.buffer.ByteBuf; -import org.springframework.stereotype.Component; - -/** - * @author samnyan (privateamusement@protonmail.com) - */ -@Component -public class LogMapper { - - private final ObjectMapper mapper; - - public LogMapper() { - mapper = new ObjectMapper(); - SimpleModule module = new SimpleModule(); - module.addSerializer(ByteBuf.class, new ByteBufSerializer()); - mapper.registerModule(module); - } - - public String write(Object o) throws JsonProcessingException { - return mapper.writeValueAsString(o); - } -}