debug: network detaching

This is useful if you want to stop the server or just analyse what is going on without having the server informed over your actions.
This commit is contained in:
Moritz Zwerger 2023-10-24 21:02:28 +02:00
parent 2c732f44d0
commit 5ee928ac87
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 49 additions and 30 deletions

View File

@ -41,6 +41,12 @@ class TestNetwork : ClientNetwork {
encrypted = true encrypted = true
} }
override fun setupCompression(threshold: Int) {
this.compressionThreshold = threshold
}
override fun detach() = Unit
override fun pauseSending(pause: Boolean) = Unit override fun pauseSending(pause: Boolean) = Unit
override fun send(packet: C2SPacket) { override fun send(packet: C2SPacket) {

View File

@ -24,12 +24,14 @@ interface ClientNetwork {
var state: ProtocolStates var state: ProtocolStates
var receive: Boolean var receive: Boolean
var compressionThreshold: Int val compressionThreshold: Int
fun connect(address: ServerAddress, native: Boolean) fun connect(address: ServerAddress, native: Boolean)
fun disconnect() fun disconnect()
fun detach()
fun setupEncryption(encrypt: Cipher, decrypt: Cipher) fun setupEncryption(encrypt: Cipher, decrypt: Cipher)
fun setupCompression(threshold: Int)
fun pauseSending(pause: Boolean) fun pauseSending(pause: Boolean)

View File

@ -55,37 +55,12 @@ class NettyClient(
private set private set
override var state by observed(ProtocolStates.HANDSHAKE) override var state by observed(ProtocolStates.HANDSHAKE)
override var compressionThreshold = -1 override var compressionThreshold = -1
set(value) {
field = value
val channel = channel ?: return
val pipeline = channel.pipeline()
if (value < 0) {
// disable
if (pipeline.get(PacketDeflater.NAME) != null) {
channel.pipeline().remove(PacketDeflater.NAME)
}
if (pipeline.get(PacketInflater.NAME) != null) {
channel.pipeline().remove(PacketInflater.NAME)
}
} else {
// enable or update
val inflater = channel.pipeline()[PacketInflater.NAME]?.nullCast<PacketInflater>()
if (inflater == null) {
channel.pipeline().addAfter(LengthDecoder.NAME, PacketInflater.NAME, PacketInflater(connection.version!!.maxPacketLength))
}
val deflater = channel.pipeline()[PacketDeflater.NAME]?.nullCast<PacketDeflater>()
if (deflater != null) {
deflater.threshold = value
} else {
channel.pipeline().addAfter(LengthEncoder.NAME, PacketDeflater.NAME, PacketDeflater(value))
}
}
}
override var encrypted: Boolean = false override var encrypted: Boolean = false
private set private set
private var channel: Channel? = null private var channel: Channel? = null
private val packetQueue: MutableList<C2SPacket> = mutableListOf() // Used for pause sending private val packetQueue: MutableList<C2SPacket> = mutableListOf() // Used for pause sending
private var sendingPaused = false private var sendingPaused = false
private var detached = false
override var receive = true override var receive = true
set(value) { set(value) {
channel?.config()?.isAutoRead = value channel?.config()?.isAutoRead = value
@ -119,6 +94,32 @@ class NettyClient(
encrypted = true encrypted = true
} }
override fun setupCompression(threshold: Int) {
val channel = channel ?: return
val pipeline = channel.pipeline()
if (threshold < 0) {
// disable
if (pipeline.get(PacketDeflater.NAME) != null) {
channel.pipeline().remove(PacketDeflater.NAME)
}
if (pipeline.get(PacketInflater.NAME) != null) {
channel.pipeline().remove(PacketInflater.NAME)
}
} else {
// enable or update
val inflater = channel.pipeline()[PacketInflater.NAME]?.nullCast<PacketInflater>()
if (inflater == null) {
channel.pipeline().addAfter(LengthDecoder.NAME, PacketInflater.NAME, PacketInflater(connection.version!!.maxPacketLength))
}
val deflater = channel.pipeline()[PacketDeflater.NAME]?.nullCast<PacketDeflater>()
if (deflater != null) {
deflater.threshold = threshold
} else {
channel.pipeline().addAfter(LengthEncoder.NAME, PacketDeflater.NAME, PacketDeflater(threshold))
}
}
}
override fun disconnect() { override fun disconnect() {
channel?.close() channel?.close()
encrypted = false encrypted = false
@ -127,6 +128,11 @@ class NettyClient(
connected = false connected = false
} }
override fun detach() {
detached = true
channel?.close()
}
override fun pauseSending(pause: Boolean) { override fun pauseSending(pause: Boolean) {
this.sendingPaused = pause this.sendingPaused = pause
if (!sendingPaused) { if (!sendingPaused) {
@ -139,11 +145,12 @@ class NettyClient(
} }
override fun send(packet: C2SPacket) { override fun send(packet: C2SPacket) {
val channel = getChannel() ?: return if (detached) return
if (sendingPaused) { if (sendingPaused) {
packetQueue += packet packetQueue += packet
return return
} }
val channel = getChannel() ?: return
packet.log((connection.nullCast<PlayConnection>()?.profiles?.other ?: OtherProfileManager.selected).log.reducedProtocolLog) packet.log((connection.nullCast<PlayConnection>()?.profiles?.other ?: OtherProfileManager.selected).log.reducedProtocolLog)
channel.writeAndFlush(packet) channel.writeAndFlush(packet)
@ -165,6 +172,7 @@ class NettyClient(
override fun channelInactive(context: ChannelHandlerContext) { override fun channelInactive(context: ChannelHandlerContext) {
Log.log(LogMessageType.NETWORK, LogLevels.VERBOSE) { "Connection closed ($address)" } Log.log(LogMessageType.NETWORK, LogLevels.VERBOSE) { "Connection closed ($address)" }
if (detached) return
connected = false connected = false
} }

View File

@ -24,7 +24,7 @@ class CompressionS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
override fun handle(connection: PlayConnection) { override fun handle(connection: PlayConnection) {
connection.network.compressionThreshold = threshold connection.network.setupCompression(threshold)
} }
override fun log(reducedLog: Boolean) { override fun log(reducedLog: Boolean) {

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger * Copyright (C) 2020-2023 Moritz Zwerger
* *
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* *
@ -22,6 +22,9 @@ import de.bixilon.minosoft.util.KUtil.format
object DebugCommand : ConnectionCommand { object DebugCommand : ConnectionCommand {
override var node = LiteralNode("debug") override var node = LiteralNode("debug")
.addChild(LiteralNode("allowFly", executor = { it.fly() }, allowArguments = true).addChild(ArgumentNode("value", BooleanParser, executable = true))) .addChild(LiteralNode("allowFly", executor = { it.fly() }, allowArguments = true).addChild(ArgumentNode("value", BooleanParser, executable = true)))
.addChild(LiteralNode("network").addChild(
LiteralNode("detach", executor = { it.connection.network.detach(); it.connection.util.sendDebugMessage("Now you are alone on the wire...") }),
))
private fun CommandStack.fly() { private fun CommandStack.fly() {