mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2024-11-21 11:55:15 +01:00
This commit is contained in:
parent
f6bd021f2f
commit
ba5f3ae82c
@ -1,8 +1,9 @@
|
||||
plugins {
|
||||
id("com.github.johnrengelman.shadow") version "6.1.0"
|
||||
id("com.github.ben-manes.versions") version "0.34.0"
|
||||
id("com.github.ben-manes.versions") version "0.36.0"
|
||||
id("com.palantir.git-version") version "0.12.3"
|
||||
application
|
||||
kotlin("jvm") version "1.4.10"
|
||||
kotlin("jvm") version "1.4.20"
|
||||
}
|
||||
|
||||
application {
|
||||
@ -14,8 +15,15 @@ java {
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
val gitVersion: groovy.lang.Closure<String> by extra
|
||||
|
||||
group = "com.github.creeper123123321.viaaas"
|
||||
version = "0.0.1-SNAPSHOT"
|
||||
version = "0.0.2-SNAPSHOT+" + try {
|
||||
gitVersion()
|
||||
} catch (e: Exception) {
|
||||
"unknown"
|
||||
}
|
||||
|
||||
extra.set("archivesBaseName", "VIAaaS")
|
||||
|
||||
repositories {
|
||||
@ -37,7 +45,7 @@ dependencies {
|
||||
implementation("net.minecrell:terminalconsoleappender:1.2.0")
|
||||
implementation("org.jline:jline-terminal-jansi:3.12.1")
|
||||
|
||||
val ktorVersion = "1.4.1"
|
||||
val ktorVersion = "1.4.2"
|
||||
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
implementation("io.ktor:ktor-network-tls-certificates:$ktorVersion")
|
||||
@ -64,3 +72,11 @@ tasks {
|
||||
dependsOn(named("dependencyUpdates"))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<ProcessResources>("processResources") {
|
||||
filesMatching("viaaas_info.json") {
|
||||
filter<org.apache.tools.ant.filters.ReplaceTokens>("tokens" to mapOf(
|
||||
"version" to project.property("version")
|
||||
))
|
||||
}
|
||||
}
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,4 +1,4 @@
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -3,10 +3,11 @@ package com.github.creeper123123321.viaaas
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.Unpooled
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelHandler
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.ChannelInitializer
|
||||
import io.netty.handler.codec.*
|
||||
import io.netty.handler.codec.ByteToMessageCodec
|
||||
import io.netty.handler.codec.DecoderException
|
||||
import io.netty.handler.codec.MessageToMessageCodec
|
||||
import io.netty.handler.flow.FlowControlHandler
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler
|
||||
import us.myles.ViaVersion.api.data.UserConnection
|
||||
@ -24,37 +25,27 @@ object ChannelInit : ChannelInitializer<Channel>() {
|
||||
val user = UserConnection(ch)
|
||||
CloudPipeline(user)
|
||||
ch.pipeline().addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
.addLast("encrypt", CloudEncryptor())
|
||||
.addLast("decrypt", CloudDecryptor())
|
||||
.addLast("frame-encoder", FrameEncoder)
|
||||
.addLast("frame-decoder", FrameDecoder())
|
||||
.addLast("compress", CloudCompressor())
|
||||
.addLast("decompress", CloudDecompressor())
|
||||
// "crypto"
|
||||
.addLast("frame", FrameCodec())
|
||||
// "compress" / dummy "decompress"
|
||||
.addLast("flow-handler", FlowControlHandler())
|
||||
.addLast("via-encoder", CloudEncodeHandler(user))
|
||||
.addLast("via-decoder", CloudDecodeHandler(user))
|
||||
.addLast("via-codec", CloudViaCodec(user))
|
||||
.addLast("handler", CloudMinecraftHandler(user, null, frontEnd = true))
|
||||
}
|
||||
}
|
||||
|
||||
class CloudDecryptor(var cipher: Cipher? = null) : MessageToMessageDecoder<ByteBuf>() {
|
||||
class CloudCrypto(val cipherDecode: Cipher, var cipherEncode: Cipher) : MessageToMessageCodec<ByteBuf, ByteBuf>() {
|
||||
override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
|
||||
val i = msg.readerIndex()
|
||||
val size = msg.readableBytes()
|
||||
if (cipher != null) {
|
||||
msg.writerIndex(i + cipher!!.update(msg.nioBuffer(), msg.nioBuffer(i, cipher!!.getOutputSize(size))))
|
||||
}
|
||||
msg.writerIndex(i + cipherDecode.update(msg.nioBuffer(), msg.nioBuffer(i, cipherDecode.getOutputSize(size))))
|
||||
out.add(msg.retain())
|
||||
}
|
||||
}
|
||||
|
||||
class CloudEncryptor(var cipher: Cipher? = null) : MessageToMessageEncoder<ByteBuf>() {
|
||||
override fun encode(ctx: ChannelHandlerContext?, msg: ByteBuf, out: MutableList<Any>) {
|
||||
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
|
||||
val i = msg.readerIndex()
|
||||
val size = msg.readableBytes()
|
||||
if (cipher != null) {
|
||||
msg.writerIndex(i + cipher!!.update(msg.nioBuffer(), msg.nioBuffer(i, cipher!!.getOutputSize(size))))
|
||||
}
|
||||
msg.writerIndex(i + cipherEncode.update(msg.nioBuffer(), msg.nioBuffer(i, cipherEncode.getOutputSize(size))))
|
||||
out.add(msg.retain())
|
||||
}
|
||||
}
|
||||
@ -62,37 +53,63 @@ class CloudEncryptor(var cipher: Cipher? = null) : MessageToMessageEncoder<ByteB
|
||||
class BackendInit(val user: UserConnection) : ChannelInitializer<Channel>() {
|
||||
override fun initChannel(ch: Channel) {
|
||||
ch.pipeline().addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
.addLast("encrypt", CloudEncryptor())
|
||||
.addLast("decrypt", CloudDecryptor())
|
||||
.addLast("frame-encoder", FrameEncoder)
|
||||
.addLast("frame-decoder", FrameDecoder())
|
||||
.addLast("compress", CloudCompressor())
|
||||
.addLast("decompress", CloudDecompressor())
|
||||
// "crypto"
|
||||
.addLast("frame", FrameCodec())
|
||||
// compress
|
||||
.addLast("handler", CloudMinecraftHandler(user, null, frontEnd = false))
|
||||
}
|
||||
}
|
||||
|
||||
class CloudDecompressor(var threshold: Int = -1) : MessageToMessageDecoder<ByteBuf>() {
|
||||
class CloudCompressionCodec(val threshold: Int) : MessageToMessageCodec<ByteBuf, ByteBuf>() {
|
||||
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
|
||||
private val inflater: Inflater = Inflater()
|
||||
private val inflater: Inflater = Inflater()// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
|
||||
private val deflater: Deflater = Deflater()
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun encode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
|
||||
val frameLength = input.readableBytes()
|
||||
val outBuf = ctx.alloc().heapBuffer()
|
||||
try {
|
||||
if (frameLength < threshold) {
|
||||
outBuf.writeByte(0)
|
||||
outBuf.writeBytes(input)
|
||||
out.add(outBuf.retain())
|
||||
return
|
||||
}
|
||||
Type.VAR_INT.writePrimitive(outBuf, frameLength)
|
||||
val inBytes = ByteArray(frameLength)
|
||||
input.readBytes(inBytes)
|
||||
deflater.setInput(inBytes, 0, frameLength)
|
||||
deflater.finish()
|
||||
while (!deflater.finished()) {
|
||||
outBuf.ensureWritable(8192)
|
||||
val wIndex = outBuf.writerIndex()
|
||||
outBuf.writerIndex(wIndex + deflater.deflate(outBuf.array(),
|
||||
outBuf.arrayOffset() + wIndex, outBuf.writableBytes()))
|
||||
}
|
||||
out.add(outBuf.retain())
|
||||
} finally {
|
||||
outBuf.release()
|
||||
deflater.reset()
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
|
||||
if (threshold == -1) {
|
||||
out.add(input.retain())
|
||||
return
|
||||
}
|
||||
if (input.isReadable) {
|
||||
val outLength = Type.VAR_INT.readPrimitive(input)
|
||||
if (outLength == 0) {
|
||||
out.add(input.readBytes(input.readableBytes()))
|
||||
} else {
|
||||
out.add(input.retain())
|
||||
return
|
||||
}
|
||||
|
||||
if (outLength < threshold) {
|
||||
throw DecoderException("Badly compressed packet - size of $outLength is below server threshold of $threshold")
|
||||
}
|
||||
if (outLength > 2097152) {
|
||||
throw DecoderException("Badly compressed packet - size of $outLength is larger than protocol maximum of 2097152")
|
||||
}
|
||||
|
||||
val temp = ByteArray(input.readableBytes())
|
||||
input.readBytes(temp)
|
||||
inflater.setInput(temp)
|
||||
@ -102,61 +119,47 @@ class CloudDecompressor(var threshold: Int = -1) : MessageToMessageDecoder<ByteB
|
||||
inflater.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CloudCompressor(var threshold: Int = -1) : MessageToByteEncoder<ByteBuf>() {
|
||||
// https://github.com/Gerrygames/ClientViaVersion/blob/master/src/main/java/de/gerrygames/the5zig/clientviaversion/netty/CompressionEncoder.java
|
||||
private val buffer = ByteArray(8192)
|
||||
private val deflater: Deflater = Deflater()
|
||||
class FrameCodec : ByteToMessageCodec<ByteBuf>() {
|
||||
val badLength = DecoderException("Invalid length!")
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun encode(ctx: ChannelHandlerContext, input: ByteBuf, out: ByteBuf) {
|
||||
if (threshold == -1) {
|
||||
out.writeBytes(input)
|
||||
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
|
||||
if (!ctx.channel().isActive) {
|
||||
input.clear() // Ignore, should prevent DoS https://github.com/SpigotMC/BungeeCord/pull/2908
|
||||
return
|
||||
}
|
||||
val frameLength = input.readableBytes()
|
||||
if (frameLength < threshold) {
|
||||
Type.VAR_INT.writePrimitive(out, 0)
|
||||
out.writeBytes(input)
|
||||
} else {
|
||||
Type.VAR_INT.writePrimitive(out, frameLength)
|
||||
val inBytes = ByteArray(frameLength)
|
||||
input.readBytes(inBytes)
|
||||
deflater.setInput(inBytes, 0, frameLength)
|
||||
deflater.finish()
|
||||
while (!deflater.finished()) {
|
||||
val written = deflater.deflate(buffer)
|
||||
out.writeBytes(buffer, 0, written)
|
||||
}
|
||||
deflater.reset()
|
||||
}
|
||||
}
|
||||
|
||||
val index = input.readerIndex()
|
||||
var nByte = 0
|
||||
val result = input.forEachByte {
|
||||
nByte++
|
||||
val hasNext = it.toInt().and(0x10000000) != 0
|
||||
if (nByte > 3) throw badLength
|
||||
hasNext
|
||||
}
|
||||
input.readerIndex(index)
|
||||
if (result == -1) return // not readable
|
||||
|
||||
@ChannelHandler.Sharable
|
||||
object FrameEncoder : MessageToMessageEncoder<ByteBuf>() {
|
||||
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList<Any>) {
|
||||
val length = ctx.alloc().buffer(5)
|
||||
Type.VAR_INT.writePrimitive(length, msg.readableBytes())
|
||||
out.add(length)
|
||||
out.add(msg.retain())
|
||||
}
|
||||
}
|
||||
|
||||
class FrameDecoder : ReplayingDecoder<ByteBuf>() {
|
||||
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
|
||||
val length = Type.VAR_INT.readPrimitive(input)
|
||||
if (length >= 2097152 || length < 0) throw DecoderException("Invalid length!")
|
||||
|
||||
if (length >= 2097152 || length < 0) throw badLength
|
||||
if (!input.isReadable(length)) {
|
||||
input.readerIndex(index)
|
||||
return
|
||||
}
|
||||
|
||||
out.add(input.readRetainedSlice(length))
|
||||
checkpoint()
|
||||
}
|
||||
|
||||
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) {
|
||||
Type.VAR_INT.writePrimitive(out, msg.readableBytes())
|
||||
out.writeBytes(msg)
|
||||
}
|
||||
}
|
||||
|
||||
class CloudDecodeHandler(val info: UserConnection) : MessageToMessageDecoder<ByteBuf>() {
|
||||
class CloudViaCodec(val info: UserConnection) : MessageToMessageCodec<ByteBuf, ByteBuf>() {
|
||||
override fun decode(ctx: ChannelHandlerContext, bytebuf: ByteBuf, out: MutableList<Any>) {
|
||||
if (!info.checkIncomingPacket()) throw CancelDecoderException.generate(null)
|
||||
if (!info.shouldTransformPacket()) {
|
||||
@ -171,9 +174,7 @@ class CloudDecodeHandler(val info: UserConnection) : MessageToMessageDecoder<Byt
|
||||
transformedBuf.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CloudEncodeHandler(val info: UserConnection) : MessageToMessageEncoder<ByteBuf>() {
|
||||
override fun encode(ctx: ChannelHandlerContext, bytebuf: ByteBuf, out: MutableList<Any>) {
|
||||
info.checkOutgoingPacket()
|
||||
if (!info.shouldTransformPacket()) {
|
||||
|
@ -3,6 +3,7 @@ package com.github.creeper123123321.viaaas
|
||||
import com.google.common.net.UrlEscapers
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import de.gerrygames.viarewind.netty.EmptyChannelHandler
|
||||
import io.ktor.client.request.*
|
||||
import io.netty.bootstrap.Bootstrap
|
||||
import io.netty.buffer.ByteBuf
|
||||
@ -28,7 +29,6 @@ import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
@ -221,13 +221,12 @@ class LoginState : MinecraftConnectionState {
|
||||
val threshold = Type.VAR_INT.readPrimitive(msg)
|
||||
|
||||
val backPipe = pipe.get(CloudMinecraftHandler::class.java).other!!.pipeline()
|
||||
backPipe.get(CloudCompressor::class.java)?.threshold = threshold
|
||||
backPipe.get(CloudDecompressor::class.java)?.threshold = threshold
|
||||
backPipe.addAfter("frame", "compress", CloudCompressionCodec(threshold))
|
||||
|
||||
forward(handler, msg)
|
||||
|
||||
pipe.get(CloudCompressor::class.java).threshold = threshold
|
||||
pipe.get(CloudDecompressor::class.java).threshold = threshold
|
||||
pipe.addAfter("frame", "compress", CloudCompressionCodec(threshold))
|
||||
pipe.addAfter("frame", "decompress", EmptyChannelHandler()) // ViaRewind compat workaround
|
||||
}
|
||||
|
||||
fun handleCryptoRequest(handler: CloudMinecraftHandler, msg: ByteBuf) {
|
||||
@ -273,8 +272,7 @@ class LoginState : MinecraftConnectionState {
|
||||
val aesEn = mcCfb8(frontKey, Cipher.ENCRYPT_MODE)
|
||||
val aesDe = mcCfb8(frontKey, Cipher.DECRYPT_MODE)
|
||||
|
||||
handler.user.channel!!.pipeline().get(CloudEncryptor::class.java).cipher = aesEn
|
||||
handler.user.channel!!.pipeline().get(CloudDecryptor::class.java).cipher = aesDe
|
||||
handler.user.channel!!.pipeline().addBefore("frame", "crypto", CloudCrypto(aesDe, aesEn))
|
||||
|
||||
generateServerHash(handler.data!!.frontId!!, frontKey, mcCryptoKey.public)
|
||||
}
|
||||
@ -302,12 +300,11 @@ class LoginState : MinecraftConnectionState {
|
||||
handler.data!!.backPublicKey!!
|
||||
)
|
||||
|
||||
if (sessionJoin.first == 0) {
|
||||
throw IllegalStateException("No browsers listening to this account, connect in /auth.html")
|
||||
} else {
|
||||
sessionJoin.second.get(15, TimeUnit.SECONDS)
|
||||
val backChan = handler.other!!
|
||||
backChan.eventLoop().submit {
|
||||
sessionJoin.whenCompleteAsync({ _, throwable ->
|
||||
if (throwable != null) {
|
||||
handler.disconnect("Online mode error: $throwable")
|
||||
} else {
|
||||
val backMsg = ByteBufAllocator.DEFAULT.buffer()
|
||||
try {
|
||||
backMsg.writeByte(1) // Packet id
|
||||
@ -318,13 +315,13 @@ class LoginState : MinecraftConnectionState {
|
||||
val backAesEn = mcCfb8(backKey, Cipher.ENCRYPT_MODE)
|
||||
val backAesDe = mcCfb8(backKey, Cipher.DECRYPT_MODE)
|
||||
|
||||
backChan.pipeline().get(CloudEncryptor::class.java).cipher = backAesEn
|
||||
backChan.pipeline().get(CloudDecryptor::class.java).cipher = backAesDe
|
||||
|
||||
backChan.pipeline().addBefore("frame", "crypto", CloudCrypto(backAesDe, backAesEn))
|
||||
} finally {
|
||||
backMsg.release()
|
||||
}
|
||||
}
|
||||
}
|
||||
}, backChan.eventLoop())
|
||||
} catch (e: Exception) {
|
||||
handler.disconnect("Online mode error: $e")
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import us.myles.ViaVersion.protocols.base.VersionProvider
|
||||
import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider
|
||||
import us.myles.ViaVersion.sponge.VersionInfo
|
||||
import us.myles.ViaVersion.sponge.util.LoggerWrapper
|
||||
import us.myles.ViaVersion.util.GsonUtil
|
||||
import us.myles.viaversion.libs.gson.JsonObject
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
@ -35,6 +36,9 @@ import java.util.concurrent.Future
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.logging.Logger
|
||||
|
||||
val viaaasVer = GsonUtil.getGson().fromJson(CloudPlatform::class.java.classLoader.getResourceAsStream("viaaas_info.json")!!
|
||||
.reader(Charsets.UTF_8).readText(), JsonObject::class.java).get("version").asString
|
||||
|
||||
object CloudBackwards : ViaBackwardsPlatform {
|
||||
val log = LoggerWrapper(LoggerFactory.getLogger("ViaBackwards"))
|
||||
override fun getDataFolder() = File("config/viabackwards")
|
||||
@ -60,8 +64,8 @@ object CloudLoader : ViaPlatformLoader {
|
||||
|
||||
object CloudCommands : ViaCommandHandler()
|
||||
object CloudInjector : ViaInjector {
|
||||
override fun getEncoderName(): String = "via-encoder"
|
||||
override fun getDecoderName() = "via-decoder"
|
||||
override fun getEncoderName(): String = "via-codec"
|
||||
override fun getDecoderName() = "via-codec"
|
||||
override fun getDump(): JsonObject = JsonObject()
|
||||
|
||||
override fun uninject() {
|
||||
@ -124,7 +128,6 @@ object CloudPlatform : ViaPlatform<Unit> {
|
||||
override fun runSync(runnable: Runnable): TaskId = CloudTask(eventLoop.submit(runnable))
|
||||
override fun runSync(p0: Runnable, p1: Long): TaskId = CloudTask(eventLoop.schedule(p0, p1 * 50L, TimeUnit.MILLISECONDS))
|
||||
override fun runRepeatingSync(p0: Runnable, p1: Long): TaskId = CloudTask(eventLoop.scheduleAtFixedRate(p0, 0, p1 * 50L, TimeUnit.MILLISECONDS))
|
||||
override fun getPlatformVersion(): String = "VIAaaS"
|
||||
override fun runAsync(p0: Runnable): TaskId = CloudTask(CompletableFuture.runAsync(p0, executor))
|
||||
override fun getLogger(): Logger = LoggerWrapper(LoggerFactory.getLogger("ViaVersion"))
|
||||
override fun getConnectionManager(): ViaConnectionManager = connMan
|
||||
@ -137,6 +140,7 @@ object CloudPlatform : ViaPlatform<Unit> {
|
||||
override fun getConfigurationProvider(): ConfigurationProvider = CloudConfig
|
||||
|
||||
override fun getPlatformName(): String = "VIAaaS"
|
||||
override fun getPlatformVersion(): String = viaaasVer
|
||||
override fun getPluginVersion(): String = VersionInfo.VERSION
|
||||
override fun isOldClientsAllowed(): Boolean = true
|
||||
override fun isProxy(): Boolean = true
|
||||
|
@ -49,7 +49,7 @@ val viaaasLogger = LoggerFactory.getLogger("VIAaaS")
|
||||
|
||||
val httpClient = HttpClient {
|
||||
defaultRequest {
|
||||
header("User-Agent", "VIAaaS")
|
||||
header("User-Agent", "VIAaaS/$viaaasVer")
|
||||
}
|
||||
install(JsonFeature) {
|
||||
serializer = GsonSerializer()
|
||||
@ -89,6 +89,10 @@ fun channelSocketFactory(): ChannelFactory<SocketChannel> {
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (System.getProperty("java.net.preferIPv6Addresses") == null) {
|
||||
System.setProperty("java.net.preferIPv6Addresses", "true")
|
||||
}
|
||||
|
||||
File("config/https.jks").apply {
|
||||
parentFile.mkdirs()
|
||||
if (!exists()) generateCertificate(this)
|
||||
@ -160,10 +164,17 @@ class VIAaaSConsole : SimpleTerminalConsole(), ViaCommandSender {
|
||||
commands["?"] = commands["help"]!!
|
||||
commands["list"] = { suggestion, _, _ ->
|
||||
if (suggestion == null) {
|
||||
sendMessage("List of player connections: ")
|
||||
Via.getPlatform().connectionManager.connections.forEach {
|
||||
sendMessage("${it.channel?.remoteAddress()} (${it.protocolInfo?.protocolVersion}) -> " +
|
||||
"(${it.protocolInfo?.serverProtocolVersion}) " +
|
||||
"${it.channel?.pipeline()?.get(CloudMinecraftHandler::class.java)?.other?.remoteAddress()}")
|
||||
val pAddr = it.channel?.remoteAddress()
|
||||
val pVer = it.protocolInfo?.protocolVersion?.let {
|
||||
ProtocolVersion.getProtocol(it)}
|
||||
val backName = it.protocolInfo?.username
|
||||
val backVer = it.protocolInfo?.serverProtocolVersion?.let {
|
||||
ProtocolVersion.getProtocol(it)}
|
||||
val backAddr = it.channel?.pipeline()?.get(CloudMinecraftHandler::class.java)?.other?.remoteAddress()
|
||||
val pName = it.channel?.pipeline()?.get(CloudMinecraftHandler::class.java)?.data?.frontName
|
||||
sendMessage("$pAddr ($pVer) ($pName) -> ($backVer) ($backName) $backAddr")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.event.Level
|
||||
import us.myles.ViaVersion.api.Via
|
||||
import java.net.SocketAddress
|
||||
import java.net.URLEncoder
|
||||
import java.security.PublicKey
|
||||
@ -29,6 +30,7 @@ import java.util.UUID
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
import kotlin.collections.set
|
||||
|
||||
|
||||
@ -107,7 +109,8 @@ class WebDashboardServer {
|
||||
|
||||
suspend fun requestSessionJoin(id: UUID, name: String, hash: String,
|
||||
address: SocketAddress, backKey: PublicKey)
|
||||
: Pair<Int, CompletableFuture<Unit>> {
|
||||
: CompletableFuture<Unit> {
|
||||
val future = viaWebServer.pendingSessionHashes.get(hash)
|
||||
var sent = 0
|
||||
viaWebServer.listeners[id]?.forEach {
|
||||
it.ws.send("""{"action": "session_hash_request", "user": "$name", "session_hash": "$hash",
|
||||
@ -116,7 +119,14 @@ class WebDashboardServer {
|
||||
it.ws.flush()
|
||||
sent++
|
||||
}
|
||||
return sent to viaWebServer.pendingSessionHashes.get(hash)
|
||||
if (sent != 0) {
|
||||
Via.getPlatform().runSync({
|
||||
future.completeExceptionally(TimeoutException("No response from browser"))
|
||||
}, 15 * 20)
|
||||
} else {
|
||||
future.completeExceptionally(IllegalStateException("No browser listening"))
|
||||
}
|
||||
return future
|
||||
}
|
||||
|
||||
suspend fun connected(ws: WebSocketServerSession) {
|
||||
|
3
src/main/resources/viaaas_info.json
Normal file
3
src/main/resources/viaaas_info.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": "@version@"
|
||||
}
|
Loading…
Reference in New Issue
Block a user