mirror of
https://github.com/MewoLab/AquaDX.git
synced 2026-02-13 13:37:59 +08:00
[O] Reduce code
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb
|
package icu.samnyan.aqua.sega.aimedb
|
||||||
|
|
||||||
import icu.samnyan.aqua.sega.aimedb.util.Encryption
|
|
||||||
import io.netty.buffer.ByteBuf
|
import io.netty.buffer.ByteBuf
|
||||||
import io.netty.channel.ChannelHandlerContext
|
import io.netty.channel.ChannelHandlerContext
|
||||||
import io.netty.handler.codec.ByteToMessageDecoder
|
import io.netty.handler.codec.ByteToMessageDecoder
|
||||||
@@ -25,24 +24,23 @@ class AimeDbDecoder : ByteToMessageDecoder() {
|
|||||||
* @param input ByteBuf in
|
* @param input ByteBuf in
|
||||||
* @param out List<Object>
|
* @param out List<Object>
|
||||||
*/
|
*/
|
||||||
@Throws(Exception::class)
|
|
||||||
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
|
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
|
||||||
if (input.readableBytes() < 16) return
|
if (input.readableBytes() < 16) return
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
length = getLength(input)
|
length = getLength(input)
|
||||||
logger.info("Aime Server Request Length: $length")
|
logger.info("AimeDB Request Length: $length")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.readableBytes() < length) return
|
if (input.readableBytes() < length) return
|
||||||
|
|
||||||
// Create a byte array to store the encrypted data
|
// Create a byte array to store the encrypted data
|
||||||
val result = Encryption.decrypt(input.readBytes(length))
|
val result = AimeDbEncryption.decrypt(input.readBytes(length))
|
||||||
|
|
||||||
val resultMap: MutableMap<String, Any> = HashMap()
|
val resultMap: MutableMap<String, Any> = HashMap()
|
||||||
resultMap["type"] = result.getShortLE(0x04).toInt()
|
resultMap["type"] = result.getShortLE(0x04).toInt()
|
||||||
resultMap["data"] = result
|
resultMap["data"] = result
|
||||||
|
|
||||||
logger.debug("Aime Server Request Type: " + resultMap["type"])
|
logger.debug("AimeDB Request Type: " + resultMap["type"])
|
||||||
|
|
||||||
out.add(resultMap)
|
out.add(resultMap)
|
||||||
}
|
}
|
||||||
@@ -55,12 +53,11 @@ class AimeDbDecoder : ByteToMessageDecoder() {
|
|||||||
*/
|
*/
|
||||||
private fun getLength(input: ByteBuf): Int {
|
private fun getLength(input: ByteBuf): Int {
|
||||||
val currentPos = input.readerIndex()
|
val currentPos = input.readerIndex()
|
||||||
val result = Encryption.decrypt(input)
|
val result = AimeDbEncryption.decrypt(input)
|
||||||
|
|
||||||
// Check the header
|
// Check the header
|
||||||
if (result.getByte(0).toInt() != 0x3e) {
|
val header = result.getByte(0).toInt()
|
||||||
throw InvalidRequestException()
|
assert(header == 0x3e) { "AimeDB: Invalid header $header" }
|
||||||
}
|
|
||||||
|
|
||||||
// Read the length from offset 6
|
// Read the length from offset 6
|
||||||
return result.getShortLE(currentPos + 6).toInt()
|
return result.getShortLE(currentPos + 6).toInt()
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb
|
package icu.samnyan.aqua.sega.aimedb
|
||||||
|
|
||||||
import icu.samnyan.aqua.sega.aimedb.util.Encryption
|
|
||||||
import io.netty.buffer.ByteBuf
|
import io.netty.buffer.ByteBuf
|
||||||
import io.netty.channel.ChannelHandlerContext
|
import io.netty.channel.ChannelHandlerContext
|
||||||
import io.netty.handler.codec.MessageToByteEncoder
|
import io.netty.handler.codec.MessageToByteEncoder
|
||||||
@@ -13,16 +12,14 @@ import org.springframework.stereotype.Component
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||||
class AimeDbEncoder : MessageToByteEncoder<Any>() {
|
class AimeDbEncoder : MessageToByteEncoder<ByteBuf>() {
|
||||||
override fun encode(ctx: ChannelHandlerContext, msg: Any, out: ByteBuf) {
|
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) {
|
||||||
if (msg is ByteBuf) {
|
msg.writerIndex(0)
|
||||||
msg.writerIndex(0)
|
msg.writeShortLE(0xa13e)
|
||||||
msg.writeShortLE(0xa13e)
|
msg.writeShortLE(0x3087)
|
||||||
msg.writeShortLE(0x3087)
|
msg.setShortLE(0x0006, msg.capacity())
|
||||||
msg.setShortLE(0x0006, msg.capacity())
|
val encryptedResp = AimeDbEncryption.encrypt(msg)
|
||||||
val encryptedResp = Encryption.encrypt(msg)
|
ctx.writeAndFlush(encryptedResp)
|
||||||
ctx.writeAndFlush(encryptedResp)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package icu.samnyan.aqua.sega.aimedb
|
||||||
|
|
||||||
|
import icu.samnyan.aqua.sega.util.ByteBufUtil
|
||||||
|
import io.netty.buffer.ByteBuf
|
||||||
|
import io.netty.buffer.Unpooled.copiedBuffer
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
import javax.crypto.Cipher
|
||||||
|
import javax.crypto.spec.SecretKeySpec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author samnyan (privateamusement@protonmail.com)
|
||||||
|
*/
|
||||||
|
object AimeDbEncryption {
|
||||||
|
val KEY = SecretKeySpec("Copyright(C)SEGA".toByteArray(StandardCharsets.UTF_8), "AES")
|
||||||
|
val cipher = Cipher.getInstance("AES/ECB/NoPadding").apply { init(Cipher.ENCRYPT_MODE, KEY) }
|
||||||
|
|
||||||
|
fun decrypt(src: ByteBuf) = copiedBuffer(cipher.doFinal(ByteBufUtil.toBytes(src)))
|
||||||
|
|
||||||
|
fun encrypt(src: ByteBuf) = copiedBuffer(cipher.doFinal(ByteBufUtil.toAllBytes(src)))
|
||||||
|
}
|
||||||
@@ -27,22 +27,22 @@ class AimeDbRequestHandler(
|
|||||||
data class AimeBaseInfo(val gameId: String, val keychipId: String)
|
data class AimeBaseInfo(val gameId: String, val keychipId: String)
|
||||||
|
|
||||||
fun getBaseInfo(input: ByteBuf) = AimeBaseInfo(
|
fun getBaseInfo(input: ByteBuf) = AimeBaseInfo(
|
||||||
gameId = input.toString(0x000a, 0x000e - 0x000a, StandardCharsets.US_ASCII),
|
gameId = input.toString(0x0a, 0x0e - 0x0a, StandardCharsets.US_ASCII),
|
||||||
keychipId = input.toString(0x0014, 0x001f - 0x0014, StandardCharsets.US_ASCII)
|
keychipId = input.toString(0x14, 0x1f - 0x14, StandardCharsets.US_ASCII)
|
||||||
)
|
)
|
||||||
|
|
||||||
final val handlers = mapOf<Int, (ByteBuf) -> ByteBuf?>(
|
final val handlers = mapOf<Int, (ByteBuf) -> ByteBuf?>(
|
||||||
0x0001 to ::doFelicaLookup,
|
0x01 to ::doFelicaLookup,
|
||||||
0x0004 to ::doLookup,
|
0x04 to ::doLookup,
|
||||||
0x0005 to ::doRegister,
|
0x05 to ::doRegister,
|
||||||
0x0009 to ::doLog,
|
0x09 to ::doLog,
|
||||||
0x000b to ::doCampaign,
|
0x0b to ::doCampaign,
|
||||||
0x000d to ::doTouch,
|
0x0d to ::doTouch,
|
||||||
0x000f to ::doLookup2,
|
0x0f to ::doLookup2,
|
||||||
0x0011 to ::doFelicaLookup2,
|
0x11 to ::doFelicaLookup2,
|
||||||
0x0013 to ::doUnknown19,
|
0x13 to ::doUnknown19,
|
||||||
0x0064 to ::doHello,
|
0x64 to ::doHello,
|
||||||
0x0066 to ::doGoodbye
|
0x66 to ::doGoodbye
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,18 +82,18 @@ class AimeDbRequestHandler(
|
|||||||
* Felica Lookup v1: Return the Felica IDm as-is
|
* Felica Lookup v1: Return the Felica IDm as-is
|
||||||
*/
|
*/
|
||||||
fun doFelicaLookup(msg: ByteBuf): ByteBuf {
|
fun doFelicaLookup(msg: ByteBuf): ByteBuf {
|
||||||
val idm = msg.slice(0x0020, 0x0028 - 0x0020).getLong(0)
|
val idm = msg.slice(0x20, 0x28 - 0x20).getLong(0)
|
||||||
val pmm = msg.slice(0x0028, 0x0030 - 0x0028).getLong(0)
|
val pmm = msg.slice(0x28, 0x30 - 0x28).getLong(0)
|
||||||
logger.info("> Felica Lookup v1 ($idm, $pmm)")
|
logger.info("> Felica Lookup v1 ($idm, $pmm)")
|
||||||
|
|
||||||
// Get the decimal represent of the hex value, same from minime
|
// Get the decimal represent of the hex value, same from minime
|
||||||
val accessCode = idm.toString().replace("-", "").padStart(20, '0')
|
val accessCode = idm.toString().replace("-", "").padStart(20, '0')
|
||||||
|
|
||||||
logger.info("> Response: $accessCode")
|
logger.info("> Response: $accessCode")
|
||||||
return Unpooled.copiedBuffer(ByteArray(0x0030)).apply {
|
return Unpooled.copiedBuffer(ByteArray(0x30)).apply {
|
||||||
setShortLE(0x0004, 0x0003)
|
setShortLE(0x04, 0x03)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
setBytes(0x0024, ByteBufUtil.decodeHexDump(accessCode))
|
setBytes(0x24, ByteBufUtil.decodeHexDump(accessCode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,8 +101,8 @@ class AimeDbRequestHandler(
|
|||||||
* Felica Lookup v2: Look up the card in the card repository, return the External ID
|
* Felica Lookup v2: Look up the card in the card repository, return the External ID
|
||||||
*/
|
*/
|
||||||
fun doFelicaLookup2(msg: ByteBuf): ByteBuf {
|
fun doFelicaLookup2(msg: ByteBuf): ByteBuf {
|
||||||
val idm = msg.slice(0x0020, 0x0028 - 0x0020).getLong(0)
|
val idm = msg.slice(0x20, 0x28 - 0x20).getLong(0)
|
||||||
val pmm = msg.slice(0x0028, 0x0030 - 0x0028).getLong(0)
|
val pmm = msg.slice(0x28, 0x30 - 0x28).getLong(0)
|
||||||
logger.info("> Felica Lookup v2 ($idm, $pmm)")
|
logger.info("> Felica Lookup v2 ($idm, $pmm)")
|
||||||
|
|
||||||
// Get the decimal represent of the hex value, same from minime
|
// Get the decimal represent of the hex value, same from minime
|
||||||
@@ -111,13 +111,13 @@ class AimeDbRequestHandler(
|
|||||||
|
|
||||||
logger.info("Response: $accessCode, $aimeId")
|
logger.info("Response: $accessCode, $aimeId")
|
||||||
return Unpooled.copiedBuffer(ByteArray(0x0140)).apply {
|
return Unpooled.copiedBuffer(ByteArray(0x0140)).apply {
|
||||||
setShortLE(0x0004, 0x0012)
|
setShortLE(0x04, 0x12)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
setLongLE(0x0020, aimeId)
|
setLongLE(0x20, aimeId)
|
||||||
setIntLE(0x0024, -0x1) // 0xFFFFFFFF
|
setIntLE(0x24, -0x1) // 0xFFFFFFFF
|
||||||
setIntLE(0x0028, -0x1) // 0xFFFFFFFF
|
setIntLE(0x28, -0x1) // 0xFFFFFFFF
|
||||||
setBytes(0x002c, ByteBufUtil.decodeHexDump(accessCode))
|
setBytes(0x2c, ByteBufUtil.decodeHexDump(accessCode))
|
||||||
setShortLE(0x0037, 0x0001)
|
setShortLE(0x37, 0x01)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,32 +125,32 @@ class AimeDbRequestHandler(
|
|||||||
* Lookup v1: Find the LUID in the database and return the External ID
|
* Lookup v1: Find the LUID in the database and return the External ID
|
||||||
*/
|
*/
|
||||||
fun doLookup(msg: ByteBuf): ByteBuf {
|
fun doLookup(msg: ByteBuf): ByteBuf {
|
||||||
val luid = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020))
|
val luid = ByteBufUtil.hexDump(msg.slice(0x20, 0x2a - 0x20))
|
||||||
logger.info("> Lookup v1 ($luid)")
|
logger.info("> Lookup v1 ($luid)")
|
||||||
|
|
||||||
val aimeId = cardService.getCardByAccessCode(luid).getOrNull()?.extId ?: -1
|
val aimeId = cardService.getCardByAccessCode(luid).getOrNull()?.extId ?: -1
|
||||||
|
|
||||||
logger.info("> Response: $aimeId")
|
logger.info("> Response: $aimeId")
|
||||||
return Unpooled.copiedBuffer(ByteArray(0x0130)).apply {
|
return Unpooled.copiedBuffer(ByteArray(0x0130)).apply {
|
||||||
setShortLE(0x0004, 0x0006)
|
setShortLE(0x04, 0x06)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
setLongLE(0x0020, aimeId)
|
setLongLE(0x20, aimeId)
|
||||||
setByte(0x0024, 0)
|
setByte(0x24, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doLookup2(msg: ByteBuf): ByteBuf {
|
fun doLookup2(msg: ByteBuf): ByteBuf {
|
||||||
val luid = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020))
|
val luid = ByteBufUtil.hexDump(msg.slice(0x20, 0x2a - 0x20))
|
||||||
logger.info("> Lookup v2 ($luid)")
|
logger.info("> Lookup v2 ($luid)")
|
||||||
|
|
||||||
val aimeId = cardService.getCardByAccessCode(luid).getOrNull()?.extId ?: -1
|
val aimeId = cardService.getCardByAccessCode(luid).getOrNull()?.extId ?: -1
|
||||||
|
|
||||||
logger.info("Response: $aimeId")
|
logger.info("Response: $aimeId")
|
||||||
return Unpooled.copiedBuffer(ByteArray(0x0130)).apply {
|
return Unpooled.copiedBuffer(ByteArray(0x0130)).apply {
|
||||||
setShortLE(0x0004, 0x0010)
|
setShortLE(0x04, 0x10)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
setLongLE(0x0020, aimeId)
|
setLongLE(0x20, aimeId)
|
||||||
setByte(0x0024, 0)
|
setByte(0x24, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ class AimeDbRequestHandler(
|
|||||||
* Register: Register a new card by access code
|
* Register: Register a new card by access code
|
||||||
*/
|
*/
|
||||||
fun doRegister(msg: ByteBuf): ByteBuf {
|
fun doRegister(msg: ByteBuf): ByteBuf {
|
||||||
val luid = ByteBufUtil.hexDump(msg.slice(0x0020, 0x002a - 0x0020))
|
val luid = ByteBufUtil.hexDump(msg.slice(0x20, 0x2a - 0x20))
|
||||||
logger.info("> Register ($luid)")
|
logger.info("> Register ($luid)")
|
||||||
|
|
||||||
var status = 0
|
var status = 0
|
||||||
@@ -173,58 +173,58 @@ class AimeDbRequestHandler(
|
|||||||
else logger.warn("> Duplicated Aime Card Register detected, access code: $luid")
|
else logger.warn("> Duplicated Aime Card Register detected, access code: $luid")
|
||||||
|
|
||||||
logger.info("> Response: $status, $aimeId")
|
logger.info("> Response: $status, $aimeId")
|
||||||
return Unpooled.copiedBuffer(ByteArray(0x0030)).apply {
|
return Unpooled.copiedBuffer(ByteArray(0x30)).apply {
|
||||||
setShortLE(0x0004, 0x0006)
|
setShortLE(0x04, 0x06)
|
||||||
setShortLE(0x0008, status)
|
setShortLE(0x08, status)
|
||||||
setLongLE(0x0020, aimeId)
|
setLongLE(0x20, aimeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log: Just log the request and return a status 1
|
* Log: Just log the request and return a status 1
|
||||||
*/
|
*/
|
||||||
fun doLog(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0020)).apply {
|
fun doLog(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x20)).apply {
|
||||||
setShortLE(0x0004, 0x000a)
|
setShortLE(0x04, 0x0a)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Campaign: Just return a status 1
|
* Campaign: Just return a status 1
|
||||||
*/
|
*/
|
||||||
fun doCampaign(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0200)).apply {
|
fun doCampaign(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0200)).apply {
|
||||||
setShortLE(0x0004, 0x000c)
|
setShortLE(0x04, 0x0c)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Touch: Just return a status 1
|
* Touch: Just return a status 1
|
||||||
*/
|
*/
|
||||||
fun doTouch(msg: ByteBuf): ByteBuf {
|
fun doTouch(msg: ByteBuf): ByteBuf {
|
||||||
val aimeId = msg.getUnsignedIntLE(0x0020)
|
val aimeId = msg.getUnsignedIntLE(0x20)
|
||||||
logger.info("> Touch ($aimeId)")
|
logger.info("> Touch ($aimeId)")
|
||||||
|
|
||||||
return Unpooled.copiedBuffer(ByteArray(0x0050)).apply {
|
return Unpooled.copiedBuffer(ByteArray(0x50)).apply {
|
||||||
setShortLE(0x0004, 0x000e)
|
setShortLE(0x04, 0x0e)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
setShortLE(0x0020, 0x006f)
|
setShortLE(0x20, 0x6f)
|
||||||
setShortLE(0x0024, 0x0001)
|
setShortLE(0x24, 0x01)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We don't know what this is, just return a status 1
|
* We don't know what this is, just return a status 1
|
||||||
*/
|
*/
|
||||||
fun doUnknown19(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0040)).apply {
|
fun doUnknown19(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x40)).apply {
|
||||||
setShortLE(0x0004, 0x0014)
|
setShortLE(0x04, 0x14)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ping: Just return a status 1
|
* Ping: Just return a status 1
|
||||||
*/
|
*/
|
||||||
fun doHello(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x0020)).apply {
|
fun doHello(msg: ByteBuf) = Unpooled.copiedBuffer(ByteArray(0x20)).apply {
|
||||||
setShortLE(0x0004, 0x0065)
|
setShortLE(0x04, 0x65)
|
||||||
setShortLE(0x0008, 1)
|
setShortLE(0x08, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doGoodbye(msg: ByteBuf) = null
|
fun doGoodbye(msg: ByteBuf) = null
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.ChannelOption;
|
|
||||||
import io.netty.channel.EventLoopGroup;
|
|
||||||
import io.netty.channel.nio.NioEventLoopGroup;
|
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
|
||||||
import io.netty.handler.logging.LogLevel;
|
|
||||||
import io.netty.handler.logging.LoggingHandler;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
public class AimeDbServer {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(AimeDbServer.class);
|
|
||||||
private final AimeDbServerInitializer aimeDbServerInitializer;
|
|
||||||
private final String address;
|
|
||||||
private final int port;
|
|
||||||
private final boolean enableAimeDb;
|
|
||||||
|
|
||||||
public AimeDbServer(AimeDbServerInitializer aimeDbServerInitializer,
|
|
||||||
@Value("${aimedb.server.address}") String address,
|
|
||||||
@Value("${aimedb.server.port}") int port,
|
|
||||||
@Value("${aimedb.server.enable}") boolean enableAimeDb) {
|
|
||||||
this.aimeDbServerInitializer = aimeDbServerInitializer;
|
|
||||||
this.address = address;
|
|
||||||
this.port = port;
|
|
||||||
this.enableAimeDb = enableAimeDb;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() throws Exception {
|
|
||||||
if (!enableAimeDb) {
|
|
||||||
logger.info("Aime DB is disabled.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
|
||||||
EventLoopGroup boss = new NioEventLoopGroup();
|
|
||||||
EventLoopGroup work = new NioEventLoopGroup();
|
|
||||||
|
|
||||||
bootstrap.group(boss, work)
|
|
||||||
.handler(new LoggingHandler(LogLevel.DEBUG))
|
|
||||||
.channel(NioServerSocketChannel.class)
|
|
||||||
.childHandler(aimeDbServerInitializer)
|
|
||||||
.option(ChannelOption.SO_BACKLOG, 128);
|
|
||||||
|
|
||||||
InetSocketAddress socket;
|
|
||||||
if(StringUtils.isNotBlank(this.address)) {
|
|
||||||
try {
|
|
||||||
socket = new InetSocketAddress(InetAddress.getByName(this.address), this.port);
|
|
||||||
} catch (UnknownHostException e) {
|
|
||||||
logger.error("UnknownHostException, please check you have set a correct aimedb.server.address.");
|
|
||||||
socket = new InetSocketAddress(this.port);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
socket = new InetSocketAddress(this.port);
|
|
||||||
}
|
|
||||||
ChannelFuture f = bootstrap.bind(socket).sync();
|
|
||||||
logger.info("Aime DB start up on " + socket);
|
|
||||||
f.channel().closeFuture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
78
src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbServer.kt
Normal file
78
src/main/java/icu/samnyan/aqua/sega/aimedb/AimeDbServer.kt
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package icu.samnyan.aqua.sega.aimedb
|
||||||
|
|
||||||
|
import io.netty.bootstrap.ServerBootstrap
|
||||||
|
import io.netty.channel.ChannelInitializer
|
||||||
|
import io.netty.channel.ChannelOption
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup
|
||||||
|
import io.netty.channel.socket.SocketChannel
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||||
|
import io.netty.handler.logging.LogLevel
|
||||||
|
import io.netty.handler.logging.LoggingHandler
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.springframework.beans.factory.config.BeanDefinition
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||||
|
import org.springframework.context.annotation.Configuration
|
||||||
|
import org.springframework.context.annotation.Scope
|
||||||
|
import org.springframework.stereotype.Component
|
||||||
|
import java.net.InetAddress
|
||||||
|
import java.net.InetSocketAddress
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "aimedb.server")
|
||||||
|
class AimeDbProps {
|
||||||
|
var enable = true
|
||||||
|
var address = "0.0.0.0"
|
||||||
|
var port = 22345
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author samnyan (privateamusement@protonmail.com)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
class AimeDbServer(
|
||||||
|
val initializer: AimeDbServerInitializer,
|
||||||
|
val props: AimeDbProps
|
||||||
|
) {
|
||||||
|
val logger: Logger = LoggerFactory.getLogger(AimeDbServer::class.java)
|
||||||
|
|
||||||
|
fun start() {
|
||||||
|
if (!props.enable) return logger.info("Aime DB is disabled.")
|
||||||
|
|
||||||
|
val bootstrap = ServerBootstrap()
|
||||||
|
.group(NioEventLoopGroup(), NioEventLoopGroup())
|
||||||
|
.handler(LoggingHandler(LogLevel.DEBUG))
|
||||||
|
.channel(NioServerSocketChannel::class.java)
|
||||||
|
.childHandler(initializer)
|
||||||
|
.option(ChannelOption.SO_BACKLOG, 128)
|
||||||
|
|
||||||
|
if (props.address.isBlank()) props.address = "0.0.0.0"
|
||||||
|
|
||||||
|
try {
|
||||||
|
val socket = InetSocketAddress(InetAddress.getByName(props.address), props.port)
|
||||||
|
|
||||||
|
val f = bootstrap.bind(socket).sync()
|
||||||
|
logger.info("Aime DB start up on $socket")
|
||||||
|
f.channel().closeFuture()
|
||||||
|
}
|
||||||
|
catch (e: UnknownHostException) {
|
||||||
|
logger.error("UnknownHostException, please check you have set a correct aimedb.server.address.")
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||||
|
class AimeDbServerInitializer(
|
||||||
|
val aimeDbRequestHandler: AimeDbRequestHandler
|
||||||
|
) : ChannelInitializer<SocketChannel>() {
|
||||||
|
override fun initChannel(ch: SocketChannel) {
|
||||||
|
ch.pipeline().apply {
|
||||||
|
addLast("encoder", AimeDbEncoder())
|
||||||
|
addLast("decoder", AimeDbDecoder())
|
||||||
|
addLast("handler", aimeDbRequestHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelInitializer
|
|
||||||
import io.netty.channel.socket.SocketChannel
|
|
||||||
import org.springframework.beans.factory.config.BeanDefinition
|
|
||||||
import org.springframework.context.annotation.Scope
|
|
||||||
import org.springframework.stereotype.Component
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
@Component
|
|
||||||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
|
||||||
class AimeDbServerInitializer(
|
|
||||||
val aimeDbRequestHandler: AimeDbRequestHandler
|
|
||||||
) : ChannelInitializer<SocketChannel>() {
|
|
||||||
override fun initChannel(ch: SocketChannel) {
|
|
||||||
ch.pipeline().apply {
|
|
||||||
addLast("encoder", AimeDbEncoder())
|
|
||||||
addLast("decoder", AimeDbDecoder())
|
|
||||||
addLast("handler", aimeDbRequestHandler)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
public class InvalidRequestException extends Exception {
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package icu.samnyan.aqua.sega.aimedb.util;
|
|
||||||
|
|
||||||
import icu.samnyan.aqua.sega.util.ByteBufUtil;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.buffer.Unpooled;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author samnyan (privateamusement@protonmail.com)
|
|
||||||
*/
|
|
||||||
public class Encryption {
|
|
||||||
|
|
||||||
private static final SecretKeySpec KEY = new SecretKeySpec("Copyright(C)SEGA".getBytes(StandardCharsets.UTF_8), "AES");
|
|
||||||
|
|
||||||
public static ByteBuf decrypt(ByteBuf src) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
|
||||||
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, KEY);
|
|
||||||
|
|
||||||
return Unpooled.copiedBuffer(cipher.doFinal(ByteBufUtil.toBytes(src)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteBuf encrypt(ByteBuf src) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
|
|
||||||
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, KEY);
|
|
||||||
byte[] bytes = cipher.doFinal(ByteBufUtil.toAllBytes(src));
|
|
||||||
return Unpooled.copiedBuffer(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user