[O] Convert more stuff to kotlin

This commit is contained in:
Azalea 2024-02-22 19:47:35 -05:00
parent 4324d655d2
commit 30a7fa7ead
10 changed files with 154 additions and 223 deletions

View File

@ -1,90 +0,0 @@
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;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author samnyan (privateamusement@protonmail.com)
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class AimeDbDecoder extends ByteToMessageDecoder {
private static final Logger logger = LoggerFactory.getLogger(AimeDbDecoder.class);
private int length = 0;
/**
* Decrypt the incoming request including frame management
* @param ctx ChannelHandlerContext
* @param in ByteBuf in
* @param out List<Object>
* @throws Exception
*/
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() < 16) {
return;
}
if (length == 0) {
length = getLength(in);
}
if (in.readableBytes() < length) {
return;
}
// Create a byte array to store the encrypted data
ByteBuf result = Encryption.decrypt(in.readBytes(length));
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("type", ((Short) result.getShortLE(0x04)).intValue());
resultMap.put("data", result);
logger.debug("Aime Server Request Type: " + resultMap.get("type"));
out.add(resultMap);
}
/**
* Get the length from request
*
* @param in the request
* @return int the length of this request
* @throws InvalidRequestException
* @throws IllegalBlockSizeException
* @throws InvalidKeyException
* @throws BadPaddingException
* @throws NoSuchAlgorithmException
* @throws NoSuchPaddingException
*/
private int getLength(ByteBuf in) throws InvalidRequestException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
int currentPos = in.readerIndex();
ByteBuf result = Encryption.decrypt(in);
// Check the header
if (result.getByte(0) != 0x3e) {
throw new InvalidRequestException();
}
// Read the length from offset 6
return result.getShortLE(currentPos + 6);
}
}

View File

@ -0,0 +1,69 @@
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
import io.netty.handler.codec.ByteToMessageDecoder
import org.slf4j.Logger
import org.slf4j.LoggerFactory
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 AimeDbDecoder : ByteToMessageDecoder() {
var length = 0
val logger: Logger = LoggerFactory.getLogger(AimeDbDecoder::class.java)
/**
* Decrypt the incoming request including frame management
* @param ctx ChannelHandlerContext
* @param input ByteBuf in
* @param out List<Object>
</Object> */
@Throws(Exception::class)
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
if (input.readableBytes() < 16) return
if (length == 0) {
length = getLength(input)
logger.info("Aime Server Request Length: $length")
}
if (input.readableBytes() < length) return
// Create a byte array to store the encrypted data
val result = Encryption.decrypt(input.readBytes(length))
val resultMap: MutableMap<String, Any> = HashMap()
resultMap["type"] = result.getShortLE(0x04).toInt()
resultMap["data"] = result
logger.debug("Aime Server 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 {
val currentPos = input.readerIndex()
val result = Encryption.decrypt(input)
// Check the header
if (result.getByte(0).toInt() != 0x3e) {
throw InvalidRequestException()
}
// Read the length from offset 6
return result.getShortLE(currentPos + 6).toInt()
}
}

View File

@ -1,32 +0,0 @@
package icu.samnyan.aqua.sega.aimedb;
import icu.samnyan.aqua.sega.aimedb.util.Encryption;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
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)
public class AimeDbEncoder extends MessageToByteEncoder {
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
if (msg instanceof ByteBuf) {
ByteBuf resp = ((ByteBuf) msg);
resp.writerIndex(0);
resp.writeShortLE(0xa13e);
resp.writeShortLE(0x3087);
resp.setShortLE(0x0006, resp.capacity());
ByteBuf encryptedResp = Encryption.encrypt(resp);
ctx.writeAndFlush(encryptedResp);
}
}
}

View File

@ -0,0 +1,28 @@
package icu.samnyan.aqua.sega.aimedb
import icu.samnyan.aqua.sega.aimedb.util.Encryption
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.MessageToByteEncoder
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 AimeDbEncoder : MessageToByteEncoder<Any>() {
override fun encode(ctx: ChannelHandlerContext, msg: Any, out: ByteBuf) {
if (msg is ByteBuf) {
msg.writerIndex(0)
msg.writeShortLE(0xa13e)
msg.writeShortLE(0x3087)
msg.setShortLE(0x0006, msg.capacity())
val encryptedResp = Encryption.encrypt(msg)
ctx.writeAndFlush(encryptedResp)
}
}
}

View File

@ -4,6 +4,8 @@ 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;
@ -18,6 +20,7 @@ import java.util.Map;
@Component
@Scope("prototype")
@AllArgsConstructor
public class AimeDbRequestHandler extends ChannelInboundHandlerAdapter {
private static final Logger logger = LoggerFactory.getLogger(AimeDbRequestHandler.class);
@ -34,27 +37,12 @@ public class AimeDbRequestHandler extends ChannelInboundHandlerAdapter {
private final Unknown19Handler unknown19Handler;
private final TouchHandler touchHandler;
@Autowired
public AimeDbRequestHandler(CampaignHandler campaignHandler, FeliCaLookupHandler feliCaLookupHandler, FeliCaLookup2Handler feliCaLookup2Handler, GoodbyeHandler goodbyeHandler, HelloHandler helloHandler, LogHandler logHandler, LookupHandler lookupHandler, Lookup2Handler lookup2Handler, RegisterHandler registerHandler, Unknown19Handler unknown19Handler, TouchHandler touchHandler) {
this.campaignHandler = campaignHandler;
this.feliCaLookupHandler = feliCaLookupHandler;
this.feliCaLookup2Handler = feliCaLookup2Handler;
this.goodbyeHandler = goodbyeHandler;
this.helloHandler = helloHandler;
this.logHandler = logHandler;
this.lookupHandler = lookupHandler;
this.lookup2Handler = lookup2Handler;
this.registerHandler = registerHandler;
this.unknown19Handler = unknown19Handler;
this.touchHandler = touchHandler;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
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");
int type = ((int) ((Map<?, ?>) msg).get("type"));
ByteBuf data = (ByteBuf) ((Map<?, ?>) msg).get("data");
switch (type) {
case 0x0001:
feliCaLookupHandler.handle(ctx, data);
@ -96,12 +84,12 @@ public class AimeDbRequestHandler extends ChannelInboundHandlerAdapter {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
logger.error("Error in AimeDB", cause);
ctx.close();
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
public void channelInactive(@NotNull ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
logger.debug("Connection closed");
}

View File

@ -41,31 +41,34 @@ public class AimeDbServer {
}
public void start() throws Exception {
if (enableAimeDb) {
ServerBootstrap bootstrap = new ServerBootstrap();
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
if (!enableAimeDb) {
logger.info("Aime DB is disabled.");
return;
}
bootstrap.group(boss, work)
.handler(new LoggingHandler(LogLevel.DEBUG))
.channel(NioServerSocketChannel.class)
.childHandler(aimeDbServerInitializer)
.option(ChannelOption.SO_BACKLOG, 128);
ServerBootstrap bootstrap = new ServerBootstrap();
EventLoopGroup boss = new NioEventLoopGroup();
EventLoopGroup work = new NioEventLoopGroup();
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 {
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);
}
ChannelFuture f = bootstrap.bind(socket).sync();
logger.info("Aime DB start up on " + socket.toString());
f.channel().closeFuture();
} else {
socket = new InetSocketAddress(this.port);
}
ChannelFuture f = bootstrap.bind(socket).sync();
logger.info("Aime DB start up on " + socket);
f.channel().closeFuture();
}
}

View File

@ -1,55 +0,0 @@
package icu.samnyan.aqua.sega.aimedb;
import icu.samnyan.aqua.sega.aimedb.handler.impl.*;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.springframework.beans.factory.annotation.Autowired;
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)
public class AimeDbServerInitializer extends ChannelInitializer<SocketChannel> {
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;
@Autowired
public AimeDbServerInitializer(CampaignHandler campaignHandler, FeliCaLookupHandler feliCaLookupHandler, FeliCaLookup2Handler feliCaLookup2Handler, GoodbyeHandler goodbyeHandler, HelloHandler helloHandler, LogHandler logHandler, LookupHandler lookupHandler, Lookup2Handler lookup2Handler, RegisterHandler registerHandler, Unknown19Handler unknown19Handler, TouchHandler touchHandler) {
this.campaignHandler = campaignHandler;
this.feliCaLookup2Handler = feliCaLookup2Handler;
this.feliCaLookupHandler = feliCaLookupHandler;
this.goodbyeHandler = goodbyeHandler;
this.helloHandler = helloHandler;
this.logHandler = logHandler;
this.lookupHandler = lookupHandler;
this.lookup2Handler = lookup2Handler;
this.registerHandler = registerHandler;
this.unknown19Handler = unknown19Handler;
this.touchHandler = touchHandler;
}
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("encoder", new AimeDbEncoder());
pipeline.addLast("decoder", new AimeDbDecoder());
pipeline.addLast("handler", new AimeDbRequestHandler(campaignHandler, feliCaLookupHandler, feliCaLookup2Handler, goodbyeHandler, helloHandler, logHandler, lookupHandler, lookup2Handler, registerHandler, unknown19Handler, touchHandler));
}
}

View File

@ -0,0 +1,24 @@
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)
}
}
}

View File

@ -10,7 +10,6 @@ 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
/**

View File

@ -20,9 +20,7 @@ import java.security.NoSuchAlgorithmException;
*/
public class Encryption {
private static final Logger logger = LoggerFactory.getLogger(Encryption.class);
private static SecretKeySpec KEY = new SecretKeySpec("Copyright(C)SEGA".getBytes(StandardCharsets.UTF_8), "AES");
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");
@ -37,5 +35,4 @@ public class Encryption {
byte[] bytes = cipher.doFinal(ByteBufUtil.toAllBytes(src));
return Unpooled.copiedBuffer(bytes);
}
}