mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2025-01-09 19:48:37 +01:00
move timeouthandler, redirect stdout, kick packet, websocket msg change
This commit is contained in:
parent
92166ecf5a
commit
1638270bd8
@ -54,7 +54,9 @@ dependencies {
|
||||
|
||||
val log4jVer = "2.14.0"
|
||||
implementation("org.apache.logging.log4j:log4j-core:$log4jVer")
|
||||
implementation("org.apache.logging.log4j:log4j-iostreams:$log4jVer")
|
||||
implementation("org.apache.logging.log4j:log4j-slf4j-impl:$log4jVer")
|
||||
implementation("org.apache.logging.log4j:log4j-jul:$log4jVer")
|
||||
implementation("org.slf4j:slf4j-api:1.7.30")
|
||||
implementation("net.minecrell:terminalconsoleappender:1.2.0")
|
||||
implementation("org.jline:jline-terminal-jansi:3.19.0")
|
||||
|
@ -8,6 +8,7 @@ import com.google.gson.JsonObject
|
||||
import io.ktor.client.request.*
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelFutureListener
|
||||
import io.netty.handler.codec.DecoderException
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.math.BigInteger
|
||||
@ -143,7 +144,7 @@ fun send(ch: Channel, obj: Any, flush: Boolean = false) {
|
||||
}
|
||||
|
||||
fun writeFlushClose(ch: Channel, obj: Any) {
|
||||
ch.writeAndFlush(obj).addListener { ch.close() }
|
||||
ch.writeAndFlush(obj).addListener(ChannelFutureListener.CLOSE)
|
||||
}
|
||||
|
||||
val secureRandom = if (VIAaaSConfig.useStrongRandom) SecureRandom.getInstanceStrong() else SecureRandom()
|
||||
|
@ -34,6 +34,8 @@ import io.netty.channel.socket.SocketChannel
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||
import io.netty.channel.socket.nio.NioSocketChannel
|
||||
import io.netty.util.concurrent.Future
|
||||
import org.apache.logging.log4j.Level
|
||||
import org.apache.logging.log4j.io.IoBuilder
|
||||
import us.myles.ViaVersion.ViaManager
|
||||
import us.myles.ViaVersion.api.Via
|
||||
import us.myles.ViaVersion.api.data.MappingDataLoader
|
||||
@ -97,6 +99,9 @@ fun main(args: Array<String>) {
|
||||
if (System.getProperty("io.netty.allocator.maxOrder") == null) {
|
||||
System.setProperty("io.netty.allocator.maxOrder", "9")
|
||||
}
|
||||
// Also stolen from Velocity
|
||||
System.setOut(IoBuilder.forLogger("STDOUT").setLevel(Level.INFO).buildPrintStream());
|
||||
System.setErr(IoBuilder.forLogger("STDERR").setLevel(Level.ERROR).buildPrintStream());
|
||||
|
||||
File("config/https.jks").apply {
|
||||
parentFile.mkdirs()
|
||||
|
@ -14,11 +14,12 @@ class BackEndInit(val connectionData: ConnectionData) : ChannelInitializer<Chann
|
||||
override fun initChannel(ch: Channel) {
|
||||
val user = UserConnection(ch, true)
|
||||
ProtocolPipeline(user)
|
||||
ch.pipeline().addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
ch.pipeline()
|
||||
// "crypto"
|
||||
.addLast("frame", FrameCodec())
|
||||
// compress
|
||||
.addLast("via-codec", ViaCodec(user))
|
||||
.addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
.addLast("mc", MinecraftCodec())
|
||||
.also {
|
||||
if (connectionData.viaBackServerVer == null) {
|
||||
@ -27,4 +28,4 @@ class BackEndInit(val connectionData: ConnectionData) : ChannelInitializer<Chann
|
||||
}
|
||||
.addLast("handler", MinecraftHandler(connectionData, frontEnd = false))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,12 @@ import java.util.concurrent.TimeUnit
|
||||
object FrontEndInit : ChannelInitializer<Channel>() {
|
||||
override fun initChannel(ch: Channel) {
|
||||
ch.pipeline()
|
||||
.addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
// "crypto"
|
||||
.addLast("frame", FrameCodec())
|
||||
// "compress"
|
||||
.addLast("flow-handler", FlowControlHandler())
|
||||
.addLast("mc", MinecraftCodec())
|
||||
.addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
.addLast("handler", MinecraftHandler(ConnectionData(frontChannel = ch), frontEnd = true))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,11 @@ import com.github.creeper123123321.viaaas.handler.forward
|
||||
import com.github.creeper123123321.viaaas.handler.is1_7
|
||||
import com.github.creeper123123321.viaaas.packet.Packet
|
||||
import com.github.creeper123123321.viaaas.packet.UnknownPacket
|
||||
import com.github.creeper123123321.viaaas.packet.play.Kick
|
||||
import com.github.creeper123123321.viaaas.packet.play.PluginMessage
|
||||
import com.github.creeper123123321.viaaas.readableToByteArray
|
||||
import com.github.creeper123123321.viaaas.writeFlushClose
|
||||
import com.google.gson.JsonPrimitive
|
||||
import io.netty.buffer.ByteBufAllocator
|
||||
import io.netty.buffer.Unpooled
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
@ -22,7 +25,7 @@ object PlayState : MinecraftConnectionState {
|
||||
override fun handlePacket(handler: MinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) {
|
||||
when {
|
||||
packet is UnknownPacket && (packet.id !in 0..127) -> throw IllegalArgumentException("Invalid packet id!")
|
||||
packet is PluginMessage -> modifyPluginMessage(handler, packet)
|
||||
packet is PluginMessage && !handler.frontEnd -> modifyPluginMessage(handler, packet)
|
||||
}
|
||||
forward(handler, packet)
|
||||
}
|
||||
@ -58,6 +61,7 @@ object PlayState : MinecraftConnectionState {
|
||||
|
||||
override fun disconnect(handler: MinecraftHandler, msg: String) {
|
||||
super.disconnect(handler, msg)
|
||||
handler.data.frontChannel.close()
|
||||
writeFlushClose(handler.data.frontChannel,
|
||||
Kick().also { it.msg = JsonPrimitive("[VIAaaS] $msg").toString() })
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@ package com.github.creeper123123321.viaaas.packet
|
||||
|
||||
import com.github.creeper123123321.viaaas.packet.handshake.Handshake
|
||||
import com.github.creeper123123321.viaaas.packet.login.*
|
||||
import com.github.creeper123123321.viaaas.packet.play.Kick
|
||||
import com.github.creeper123123321.viaaas.packet.play.PluginMessage
|
||||
import com.github.creeper123123321.viaaas.packet.status.StatusPing
|
||||
import com.github.creeper123123321.viaaas.packet.status.StatusPong
|
||||
@ -32,6 +33,17 @@ object PacketRegistry {
|
||||
register(Range.all(), State.STATUS, 1, true, ::StatusPing)
|
||||
register(Range.all(), State.STATUS, 0, false, ::StatusResponse)
|
||||
register(Range.all(), State.STATUS, 1, false, ::StatusPong)
|
||||
register(
|
||||
::Kick, State.PLAY, false, mapOf(
|
||||
Range.closed(ProtocolVersion.v1_7_1.version, ProtocolVersion.v1_8.version) to 0x40,
|
||||
Range.closed(ProtocolVersion.v1_9.version, ProtocolVersion.v1_12_2.version) to 0x1A,
|
||||
Range.closed(ProtocolVersion.v1_13.version, ProtocolVersion.v1_13_2.version) to 0x1B,
|
||||
Range.closed(ProtocolVersion.v1_14.version, ProtocolVersion.v1_14_4.version) to 0x1A,
|
||||
Range.closed(ProtocolVersion.v1_15.version, ProtocolVersion.v1_15_2.version) to 0x1B,
|
||||
Range.closed(ProtocolVersion.v1_16.version, ProtocolVersion.v1_16_1.version) to 0x1A,
|
||||
Range.closed(ProtocolVersion.v1_16_2.version, ProtocolVersion.v1_16_4.version) to 0x19
|
||||
)
|
||||
)
|
||||
register(
|
||||
::PluginMessage, State.PLAY, true, mapOf(
|
||||
Range.closed(ProtocolVersion.v1_7_1.version, ProtocolVersion.v1_8.version) to 0x17,
|
||||
|
@ -0,0 +1,16 @@
|
||||
package com.github.creeper123123321.viaaas.packet.play
|
||||
|
||||
import com.github.creeper123123321.viaaas.packet.Packet
|
||||
import io.netty.buffer.ByteBuf
|
||||
import us.myles.ViaVersion.api.type.Type
|
||||
|
||||
class Kick : Packet {
|
||||
lateinit var msg: String
|
||||
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
|
||||
msg = Type.STRING.read(byteBuf)
|
||||
}
|
||||
|
||||
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
|
||||
Type.STRING.write(byteBuf, msg)
|
||||
}
|
||||
}
|
@ -43,7 +43,6 @@ class ViaWebApp {
|
||||
}
|
||||
} catch (ignored: ClosedChannelException) {
|
||||
} catch (e: Exception) {
|
||||
webLogger.info("${call.request.local.remoteHost} (O: ${call.request.origin.remoteHost}) exception: $e")
|
||||
viaWebServer.onException(this, e)
|
||||
this.close(CloseReason(CloseReason.Codes.INTERNAL_ERROR, "INTERNAL ERROR"))
|
||||
} finally {
|
||||
|
@ -1,23 +1,30 @@
|
||||
package com.github.creeper123123321.viaaas.web
|
||||
|
||||
import com.github.creeper123123321.viaaas.config.VIAaaSConfig
|
||||
import com.google.common.collect.Sets
|
||||
import com.google.common.util.concurrent.RateLimiter
|
||||
import io.ktor.features.*
|
||||
import io.ktor.websocket.*
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
data class WebClient(
|
||||
val server: WebDashboardServer,
|
||||
val ws: WebSocketServerSession,
|
||||
val state: WebState,
|
||||
) {
|
||||
val listenedIds: MutableSet<UUID> = Collections.newSetFromMap(ConcurrentHashMap())
|
||||
object IdGen {
|
||||
val atInt = AtomicInteger()
|
||||
fun next() = atInt.getAndAdd(1)
|
||||
}
|
||||
val id = "${ws.call.request.local.host}(${ws.call.request.origin.host})-${IdGen.next()}"
|
||||
val listenedIds: MutableSet<UUID> = Sets.newConcurrentHashSet()
|
||||
val rateLimiter = RateLimiter.create(VIAaaSConfig.rateLimitWs)
|
||||
|
||||
fun listenId(uuid: UUID): Boolean {
|
||||
if (listenedIds.size >= VIAaaSConfig.listeningWsLimit) return false // This is getting insane
|
||||
server.listeners.computeIfAbsent(uuid) { Collections.newSetFromMap(ConcurrentHashMap()) }
|
||||
.add(this)
|
||||
server.listeners.computeIfAbsent(uuid) { Sets.newConcurrentHashSet() }.add(this)
|
||||
listenedIds.add(uuid)
|
||||
return true
|
||||
}
|
||||
|
@ -3,10 +3,12 @@ package com.github.creeper123123321.viaaas.web
|
||||
import com.github.creeper123123321.viaaas.httpClient
|
||||
import com.github.creeper123123321.viaaas.parseUndashedId
|
||||
import com.github.creeper123123321.viaaas.viaWebServer
|
||||
import com.github.creeper123123321.viaaas.webLogger
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import com.google.common.cache.CacheLoader
|
||||
import com.google.gson.JsonObject
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.features.*
|
||||
import io.ktor.http.cio.websocket.*
|
||||
import io.ktor.websocket.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@ -52,26 +54,24 @@ class WebDashboardServer {
|
||||
id: UUID, name: String, hash: String,
|
||||
address: SocketAddress, backAddress: SocketAddress
|
||||
): CompletableFuture<Unit> {
|
||||
val future = viaWebServer.pendingSessionHashes.get(hash)
|
||||
var sent = 0
|
||||
viaWebServer.listeners[id]?.forEach {
|
||||
it.ws.send(
|
||||
JsonObject().also {
|
||||
it.addProperty("action", "session_hash_request")
|
||||
it.addProperty("user", name)
|
||||
it.addProperty("session_hash", hash)
|
||||
it.addProperty("message", "Client is $address, backend is $backAddress")
|
||||
}.toString()
|
||||
)
|
||||
it.ws.flush()
|
||||
sent++
|
||||
}
|
||||
if (sent != 0) {
|
||||
val future = pendingSessionHashes.get(hash)
|
||||
if (listeners[id]?.isEmpty() != false) {
|
||||
future.completeExceptionally(IllegalStateException("No browser listening"))
|
||||
} else {
|
||||
listeners[id]?.forEach {
|
||||
it.ws.send(
|
||||
JsonObject().also {
|
||||
it.addProperty("action", "session_hash_request")
|
||||
it.addProperty("user", name)
|
||||
it.addProperty("session_hash", hash)
|
||||
it.addProperty("message", "Client is $address, backend is $backAddress")
|
||||
}.toString()
|
||||
)
|
||||
it.ws.flush()
|
||||
}
|
||||
Via.getPlatform().runSync({
|
||||
future.completeExceptionally(TimeoutException("No response from browser"))
|
||||
}, 15 * 20)
|
||||
} else {
|
||||
future.completeExceptionally(IllegalStateException("No browser listening"))
|
||||
}
|
||||
return future
|
||||
}
|
||||
@ -79,24 +79,27 @@ class WebDashboardServer {
|
||||
suspend fun connected(ws: WebSocketServerSession) {
|
||||
val loginState = WebLogin()
|
||||
val client = WebClient(this, ws, loginState)
|
||||
webLogger.info("+ WS: ${client.id}")
|
||||
clients[ws] = client
|
||||
loginState.start(client)
|
||||
}
|
||||
|
||||
suspend fun onMessage(ws: WebSocketSession, msg: String) {
|
||||
suspend fun onMessage(ws: WebSocketServerSession, msg: String) {
|
||||
val client = clients[ws]!!
|
||||
client.rateLimiter.acquire()
|
||||
client.state.onMessage(client, msg)
|
||||
}
|
||||
|
||||
suspend fun disconnected(ws: WebSocketSession) {
|
||||
suspend fun disconnected(ws: WebSocketServerSession) {
|
||||
val client = clients[ws]!!
|
||||
webLogger.info("- WS: ${client.id}")
|
||||
client.state.disconnected(client)
|
||||
clients.remove(ws)
|
||||
}
|
||||
|
||||
suspend fun onException(ws: WebSocketSession, exception: java.lang.Exception) {
|
||||
suspend fun onException(ws: WebSocketServerSession, exception: Exception) {
|
||||
val client = clients[ws]!!
|
||||
webLogger.info("WS Error: ${client.id} $exception")
|
||||
client.state.onException(client, exception)
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class WebLogin : WebState {
|
||||
| "username": "$username", "uuid": "$uuid", "token": "$token"}""".trimMargin()
|
||||
)
|
||||
|
||||
webLogger.info("Token gen: ${webClient.ws.call.request.local.remoteHost} (O: ${webClient.ws.call.request.origin.remoteHost}): offline $username")
|
||||
webLogger.info("Token gen: ${webClient.id}: offline $username $uuid")
|
||||
}
|
||||
"minecraft_id_login" -> {
|
||||
val username = obj.get("username").asString
|
||||
@ -54,10 +54,10 @@ class WebLogin : WebState {
|
||||
| "username": "$mcIdUser", "uuid": "$uuid", "token": "$token"}""".trimMargin()
|
||||
)
|
||||
|
||||
webLogger.info("Token gen: ${webClient.ws.call.request.local.remoteHost} (O: ${webClient.ws.call.request.origin.remoteHost}): $mcIdUser $uuid")
|
||||
webLogger.info("Token gen: ${webClient.id}: $mcIdUser $uuid")
|
||||
} else {
|
||||
webClient.ws.send("""{"action": "login_result", "success": false}""")
|
||||
webLogger.info("Token gen fail: ${webClient.ws.call.request.local.remoteHost} (O: ${webClient.ws.call.request.origin.remoteHost}): $username")
|
||||
webLogger.info("Token gen fail: ${webClient.id}: $username")
|
||||
}
|
||||
}
|
||||
"listen_login_requests" -> {
|
||||
@ -65,11 +65,11 @@ class WebLogin : WebState {
|
||||
val user = webClient.server.loginTokens.getIfPresent(token)
|
||||
if (user != null && webClient.listenId(user)) {
|
||||
webClient.ws.send("""{"action": "listen_login_requests_result", "token": "$token", "success": true, "user": "$user"}""")
|
||||
webLogger.info("Listen: ${webClient.ws.call.request.local.remoteHost} (O: ${webClient.ws.call.request.origin.remoteHost}): $user")
|
||||
webLogger.info("Listen: ${webClient.id}: $user")
|
||||
} else {
|
||||
webClient.server.loginTokens.invalidate(token)
|
||||
webClient.ws.send("""{"action": "listen_login_requests_result", "token": "$token", "success": false}""")
|
||||
webLogger.info("Token fail: ${webClient.ws.call.request.local.remoteHost} (O: ${webClient.ws.call.request.origin.remoteHost})")
|
||||
webLogger.info("Token fail: ${webClient.id}")
|
||||
}
|
||||
}
|
||||
"unlisten_login_requests" -> {
|
||||
|
Loading…
Reference in New Issue
Block a user