fixed mojang account refresh, code cleanup, parse status packets

This commit is contained in:
creeper123123321 2021-02-06 20:09:51 -03:00
parent e966a45540
commit 764f849d79
4 changed files with 106 additions and 97 deletions

View File

@ -51,7 +51,7 @@ class BackendInit(val connectionData: ConnectionData) : ChannelInitializer<Chann
} }
} }
class CloudMinecraftCodec: MessageToMessageCodec<ByteBuf, Packet>() { class CloudMinecraftCodec : MessageToMessageCodec<ByteBuf, Packet>() {
override fun encode(ctx: ChannelHandlerContext, msg: Packet, out: MutableList<Any>) { override fun encode(ctx: ChannelHandlerContext, msg: Packet, out: MutableList<Any>) {
if (!ctx.channel().isActive) return if (!ctx.channel().isActive) return
val buf = ByteBufAllocator.DEFAULT.buffer() val buf = ByteBufAllocator.DEFAULT.buffer()
@ -67,9 +67,13 @@ class CloudMinecraftCodec: MessageToMessageCodec<ByteBuf, Packet>() {
override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) { override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
if (!ctx.channel().isActive || !msg.isReadable) return if (!ctx.channel().isActive || !msg.isReadable) return
val handler = ctx.pipeline().get(CloudMinecraftHandler::class.java) val handler = ctx.pipeline().get(CloudMinecraftHandler::class.java)
out.add(PacketRegistry.decode(msg, out.add(
PacketRegistry.decode(
msg,
handler.data.frontVer ?: 0, handler.data.frontVer ?: 0,
handler.data.state.state, handler.frontEnd)) handler.data.state.state, handler.frontEnd
)
)
if (msg.isReadable) throw IllegalStateException("Remaining bytes!!!") if (msg.isReadable) throw IllegalStateException("Remaining bytes!!!")
} }
} }
@ -197,31 +201,17 @@ class FrameCodec : ByteToMessageCodec<ByteBuf>() {
class CloudViaCodec(val info: UserConnection) : MessageToMessageCodec<ByteBuf, ByteBuf>() { class CloudViaCodec(val info: UserConnection) : MessageToMessageCodec<ByteBuf, ByteBuf>() {
override fun decode(ctx: ChannelHandlerContext, bytebuf: ByteBuf, out: MutableList<Any>) { override fun decode(ctx: ChannelHandlerContext, bytebuf: ByteBuf, out: MutableList<Any>) {
if (!info.checkIncomingPacket()) throw CancelDecoderException.generate(null) if (!info.checkIncomingPacket()) throw CancelDecoderException.generate(null)
if (!info.shouldTransformPacket()) { if (info.shouldTransformPacket()) {
info.transformIncoming(bytebuf, CancelDecoderException::generate)
}
out.add(bytebuf.retain()) out.add(bytebuf.retain())
return
}
val transformedBuf: ByteBuf = ctx.alloc().buffer().writeBytes(bytebuf)
try {
info.transformIncoming(transformedBuf, CancelDecoderException::generate)
out.add(transformedBuf.retain())
} finally {
transformedBuf.release()
}
} }
override fun encode(ctx: ChannelHandlerContext, bytebuf: ByteBuf, out: MutableList<Any>) { override fun encode(ctx: ChannelHandlerContext, bytebuf: ByteBuf, out: MutableList<Any>) {
if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null) if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null)
if (!info.shouldTransformPacket()) { if (info.shouldTransformPacket()) {
info.transformOutgoing(bytebuf, CancelEncoderException::generate)
}
out.add(bytebuf.retain()) out.add(bytebuf.retain())
return
}
val transformedBuf: ByteBuf = ctx.alloc().buffer().writeBytes(bytebuf)
try {
info.transformOutgoing(transformedBuf, CancelEncoderException::generate)
out.add(transformedBuf.retain())
} finally {
transformedBuf.release()
}
} }
} }

View File

@ -6,14 +6,12 @@ import com.google.gson.Gson
import com.google.gson.JsonObject import com.google.gson.JsonObject
import io.ktor.client.request.* import io.ktor.client.request.*
import io.netty.bootstrap.Bootstrap import io.netty.bootstrap.Bootstrap
import io.netty.buffer.ByteBufAllocator
import io.netty.channel.* import io.netty.channel.*
import io.netty.channel.socket.SocketChannel import io.netty.channel.socket.SocketChannel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import us.myles.ViaVersion.api.type.Type
import us.myles.ViaVersion.exception.CancelCodecException import us.myles.ViaVersion.exception.CancelCodecException
import us.myles.ViaVersion.packets.State import us.myles.ViaVersion.packets.State
import java.math.BigInteger import java.math.BigInteger
@ -270,7 +268,7 @@ class LoginState : MinecraftConnectionState {
cryptoRequest.publicKey = mcCryptoKey.public cryptoRequest.publicKey = mcCryptoKey.public
cryptoRequest.token = token cryptoRequest.token = token
frontHandler.data.frontChannel.writeAndFlush(cryptoRequest) sendPacket(frontHandler.data.frontChannel, cryptoRequest, true)
} }
fun handleCryptoRequest(handler: CloudMinecraftHandler, cryptoRequest: CryptoRequest) { fun handleCryptoRequest(handler: CloudMinecraftHandler, cryptoRequest: CryptoRequest) {
@ -386,16 +384,9 @@ class LoginState : MinecraftConnectionState {
override fun disconnect(handler: CloudMinecraftHandler, msg: String) { override fun disconnect(handler: CloudMinecraftHandler, msg: String) {
super.disconnect(handler, msg) super.disconnect(handler, msg)
val packet = ByteBufAllocator.DEFAULT.buffer() val packet = LoginDisconnect()
try { packet.msg = Gson().toJson("[VIAaaS] §c$msg")
packet.writeByte(0) // id 0 disconnect sendFlushPacketClose(handler.data.frontChannel, packet)
Type.STRING.write(packet, Gson().toJson("[VIAaaS] §c$msg"))
handler.data.frontChannel
.writeAndFlush(packet.retain())
.addListener { handler.data.frontChannel.close() }
} finally {
packet.release()
}
} }
} }
@ -404,25 +395,17 @@ object StatusState : MinecraftConnectionState {
get() = State.STATUS get() = State.STATUS
override fun handlePacket(handler: CloudMinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) { override fun handlePacket(handler: CloudMinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) {
if ((packet as UnknownPacket).id !in 0..1) throw IllegalArgumentException("Invalid packet id!") if (packet is UnknownPacket) throw IllegalArgumentException("Invalid packet")
forward(handler, packet) forward(handler, packet)
} }
override fun disconnect(handler: CloudMinecraftHandler, msg: String) { override fun disconnect(handler: CloudMinecraftHandler, msg: String) {
super.disconnect(handler, msg) super.disconnect(handler, msg)
val packet = ByteBufAllocator.DEFAULT.buffer() val packet = StatusResponse()
try { packet.json = """{"version": {"name": "VIAaaS", "protocol": -1}, "players": {"max": 0, "online": 0,
packet.writeByte(0) // id 0 disconnect | "sample": []}, "description": {"text": ${Gson().toJson("§c$msg")}}}""".trimMargin()
Type.STRING.write( sendFlushPacketClose(handler.data.frontChannel, packet)
packet, """{"version": {"name": "VIAaaS", "protocol": -1}, "players":
| {"max": 0, "online": 0, "sample": []}, "description": {"text": ${Gson().toJson("§c$msg")}}}""".trimMargin()
)
handler.data.frontChannel.writeAndFlush(packet.retain())
.addListener { handler.data.frontChannel.close() }
} finally {
packet.release()
}
} }
} }
@ -479,18 +462,20 @@ fun generateServerHash(serverId: String, sharedSecret: ByteArray?, key: PublicKe
return twosComplementHexdigest(digest.digest()) return twosComplementHexdigest(digest.digest())
} }
private fun sendFlushPacketClose(ch: Channel, packet: Packet) {
ch.writeAndFlush(packet).addListener { ch.close() }
}
private fun forward(handler: CloudMinecraftHandler, packet: Packet, flush: Boolean = false) { private fun forward(handler: CloudMinecraftHandler, packet: Packet, flush: Boolean = false) {
val msg = ByteBufAllocator.DEFAULT.buffer() sendPacket(handler.other!!, packet, flush)
try { }
val ch = handler.other!!
private fun sendPacket(ch: Channel, packet: Packet, flush: Boolean = false) {
if (flush) { if (flush) {
ch.writeAndFlush(packet, ch.voidPromise()) ch.writeAndFlush(packet, ch.voidPromise())
} else { } else {
ch.write(packet, ch.voidPromise()) ch.write(packet, ch.voidPromise())
} }
} finally {
msg.release()
}
} }
private fun resolveSrv(address: String, port: Int): Pair<String, Int> { private fun resolveSrv(address: String, port: Int): Pair<String, Int> {

View File

@ -24,40 +24,29 @@ object PacketRegistry {
val entries = mutableListOf<RegistryEntry>() val entries = mutableListOf<RegistryEntry>()
init { init {
entries.add( register(Range.all(), State.HANDSHAKE, 0, true, ::HandshakePacket)
RegistryEntry(Range.all(), State.HANDSHAKE, 0, true, ::HandshakePacket, HandshakePacket::class.java) register(Range.all(), State.LOGIN, 0, true, ::LoginStart)
) register(Range.all(), State.LOGIN, 1, true, ::CryptoResponse)
entries.add( register(Range.atLeast(ProtocolVersion.v1_13.version), State.LOGIN, 2, true, ::PluginResponse)
RegistryEntry(Range.all(), State.LOGIN, 0, true, ::LoginStart, LoginStart::class.java) register(Range.all(), State.LOGIN, 0, false, ::LoginDisconnect)
) register(Range.all(), State.LOGIN, 1, false, ::CryptoRequest)
entries.add( register(Range.all(), State.LOGIN, 2, false, ::LoginSuccess)
RegistryEntry(Range.all(), State.LOGIN, 1, true, ::CryptoResponse, CryptoResponse::class.java) register(Range.all(), State.LOGIN, 3, false, ::SetCompression)
) register(Range.all(), State.LOGIN, 4, false, ::PluginRequest)
entries.add( register(Range.all(), State.STATUS, 0, true, ::StatusRequest)
RegistryEntry( register(Range.all(), State.STATUS, 1, true, ::StatusPing)
Range.atLeast(ProtocolVersion.v1_13.version), register(Range.all(), State.STATUS, 0, false, ::StatusResponse)
State.LOGIN, register(Range.all(), State.STATUS, 1, false, ::StatusPong)
2, }
true,
::PluginResponse, inline fun <reified P : Packet> register(
PluginResponse::class.java protocol: Range<Int>,
) state: State,
) id: Int,
entries.add( serverBound: Boolean,
RegistryEntry(Range.all(), State.LOGIN, 0, false, ::LoginDisconnect, LoginDisconnect::class.java) constructor: Supplier<P>
) ) {
entries.add( entries.add(RegistryEntry(protocol, state, id, serverBound, constructor, P::class.java))
RegistryEntry(Range.all(), State.LOGIN, 1, false, ::CryptoRequest, CryptoRequest::class.java)
)
entries.add(
RegistryEntry(Range.all(), State.LOGIN, 2, false, ::LoginSuccess, LoginSuccess::class.java)
)
entries.add(
RegistryEntry(Range.all(), State.LOGIN, 3, false, ::SetCompression, SetCompression::class.java)
)
entries.add(
RegistryEntry(Range.all(), State.LOGIN, 4, false, ::PluginRequest, PluginRequest::class.java)
)
} }
data class RegistryEntry( data class RegistryEntry(
@ -65,7 +54,7 @@ object PacketRegistry {
val state: State, val state: State,
val id: Int, val id: Int,
val serverBound: Boolean, val serverBound: Boolean,
val constructor: Supplier<Packet>, val constructor: Supplier<out Packet>,
val packetClass: Class<out Packet> val packetClass: Class<out Packet>
) )
@ -304,3 +293,44 @@ class PluginRequest : Packet {
byteBuf.writeBytes(data) byteBuf.writeBytes(data)
} }
} }
class StatusResponse : Packet {
lateinit var json: String
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
json = Type.STRING.read(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.STRING.write(byteBuf, json)
}
}
class StatusRequest: Packet {
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
}
}
class StatusPing: Packet {
var number by Delegates.notNull<Long>()
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
number = byteBuf.readLong()
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
byteBuf.writeLong(number)
}
}
class StatusPong: Packet {
var number by Delegates.notNull<Long>()
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
number = byteBuf.readLong()
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
byteBuf.writeLong(number)
}
}

View File

@ -179,9 +179,9 @@ function refreshMojangAccount(it) {
headers: {"content-type": "application/json"}, headers: {"content-type": "application/json"},
}).then(data => { }).then(data => {
if (!isSuccess(data.status)) throw "not success"; if (!isSuccess(data.status)) throw "not success";
console.log("refreshed " + data.selectedProfile.id);
return data.json(); return data.json();
}).then((json) => { }).then((json) => {
console.log("refreshed " + json.selectedProfile.id);
removeMcAccount(data.selectedProfile.id); removeMcAccount(data.selectedProfile.id);
return storeMcAccount(json.accessToken, json.clientToken, json.selectedProfile.name, json.selectedProfile.id); return storeMcAccount(json.accessToken, json.clientToken, json.selectedProfile.name, json.selectedProfile.id);
}); });
@ -252,6 +252,10 @@ function addAction(text, onClick) {
actions.appendChild(p); actions.appendChild(p);
} }
function findAccountByMcName(name) {
return getMcAccounts().reverse().find(it => it.name.toLowerCase() == name.toLowerCase());
}
function onSocketMsg(event) { function onSocketMsg(event) {
console.log(event.data.toString()); console.log(event.data.toString());
let parsed = JSON.parse(event.data); let parsed = JSON.parse(event.data);
@ -275,7 +279,7 @@ function onSocketMsg(event) {
} }
} else if (parsed.action == "session_hash_request") { } else if (parsed.action == "session_hash_request") {
if (confirm("Allow auth impersonation from VIAaaS instance? info: " + JSON.stringify(parsed))) { if (confirm("Allow auth impersonation from VIAaaS instance? info: " + JSON.stringify(parsed))) {
let account = getMcAccounts().reverse().find(it => it.name.toLowerCase() == parsed.user.toLowerCase()); let account = findAccountByMcName(parsed.user);
if (account) { if (account) {
getMcUserToken(account).then((data) => { getMcUserToken(account).then((data) => {
return joinGame(data.accessToken, data.id, parsed.session_hash); return joinGame(data.accessToken, data.id, parsed.session_hash);