package org.openrs2.game.net.login import io.netty.buffer.Unpooled import io.netty.channel.ChannelFutureListener import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler import io.netty.handler.codec.DelimiterBasedFrameDecoder import io.netty.handler.codec.string.StringDecoder import org.openrs2.buffer.copiedBuffer import org.openrs2.game.net.jaggrab.JaggrabChannelHandler import org.openrs2.game.net.js5.Js5ChannelHandler import org.openrs2.protocol.Rs2Decoder import org.openrs2.protocol.Rs2Encoder import org.openrs2.protocol.jaggrab.JaggrabRequestDecoder import org.openrs2.protocol.js5.Js5RequestDecoder import org.openrs2.protocol.js5.Js5ResponseEncoder import org.openrs2.protocol.js5.XorDecoder import org.openrs2.protocol.login.LoginRequest import org.openrs2.protocol.login.LoginResponse import javax.inject.Inject import javax.inject.Provider public class LoginChannelHandler @Inject constructor( private val js5HandlerProvider: Provider, private val jaggrabHandler: JaggrabChannelHandler ) : SimpleChannelInboundHandler() { override fun channelActive(ctx: ChannelHandlerContext) { ctx.read() } override fun channelRead0(ctx: ChannelHandlerContext, msg: LoginRequest) { when (msg) { is LoginRequest.InitJs5RemoteConnection -> handleInitJs5RemoteConnection(ctx, msg) is LoginRequest.InitJaggrabConnection -> handleInitJaggrabConnection(ctx) } } private fun handleInitJs5RemoteConnection(ctx: ChannelHandlerContext, msg: LoginRequest.InitJs5RemoteConnection) { if (msg.build != BUILD) { ctx.write(LoginResponse.ClientOutOfDate).addListener(ChannelFutureListener.CLOSE) return } ctx.pipeline().addLast( XorDecoder(), Js5RequestDecoder(), Js5ResponseEncoder, js5HandlerProvider.get() ) ctx.pipeline().remove(Rs2Decoder::class.java) ctx.write(LoginResponse.Js5Ok).addListener { ctx.pipeline().remove(Rs2Encoder::class.java) ctx.pipeline().remove(this) } } private fun handleInitJaggrabConnection(ctx: ChannelHandlerContext) { ctx.pipeline().addLast( DelimiterBasedFrameDecoder(JAGGRAB_MAX_FRAME_LENGTH, JAGGRAB_DELIMITER), StringDecoder(Charsets.UTF_8), JaggrabRequestDecoder, jaggrabHandler ) ctx.pipeline().remove(Rs2Decoder::class.java) ctx.pipeline().remove(Rs2Encoder::class.java) ctx.pipeline().remove(this) } override fun channelReadComplete(ctx: ChannelHandlerContext) { ctx.flush() } private companion object { private const val BUILD = 550 private const val JAGGRAB_MAX_FRAME_LENGTH = 4096 private val JAGGRAB_DELIMITER = Unpooled.unreleasableBuffer(copiedBuffer("\n\n")) } }