mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2024-11-04 09:30:00 +01:00
protocol cache expiration, fix dns blocking thread, fix 1.8 fallback
This commit is contained in:
parent
942908341a
commit
4ce8bcc511
@ -7,13 +7,16 @@ import com.viaversion.viaversion.protocol.ProtocolPipelineImpl
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelInitializer
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.URI
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class BackEndInit(val connectionData: ConnectionData) : ChannelInitializer<Channel>() {
|
||||
class BackEndInit(val connectionData: ConnectionData, val proxyUri: URI?, val proxyAddress: InetSocketAddress?) :
|
||||
ChannelInitializer<Channel>() {
|
||||
override fun initChannel(ch: Channel) {
|
||||
val user = UserConnectionImpl(ch, true)
|
||||
ProtocolPipelineImpl(user)
|
||||
ch.pipeline().also { addProxyHandler(it) }
|
||||
ch.pipeline().also { addProxyHandler(it, proxyUri, proxyAddress) }
|
||||
// "crypto"
|
||||
.addLast("frame", FrameCodec())
|
||||
// compress
|
||||
|
@ -1,8 +1,6 @@
|
||||
package com.viaversion.aas.handler
|
||||
|
||||
import com.viaversion.aas.AspirinServer
|
||||
import com.viaversion.aas.codec.packet.Packet
|
||||
import com.viaversion.aas.config.VIAaaSConfig
|
||||
import com.viaversion.aas.readRemainingBytes
|
||||
import com.viaversion.aas.send
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
|
||||
@ -14,6 +12,7 @@ import io.netty.handler.proxy.HttpProxyHandler
|
||||
import io.netty.handler.proxy.Socks4ProxyHandler
|
||||
import io.netty.handler.proxy.Socks5ProxyHandler
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.URI
|
||||
|
||||
fun forward(handler: MinecraftHandler, packet: Packet, flush: Boolean = false) {
|
||||
send(handler.other!!, packet, flush)
|
||||
@ -21,10 +20,8 @@ fun forward(handler: MinecraftHandler, packet: Packet, flush: Boolean = false) {
|
||||
|
||||
fun is17(handler: MinecraftHandler) = handler.data.frontVer!! <= ProtocolVersion.v1_7_6.version
|
||||
|
||||
fun addProxyHandler(pipe: ChannelPipeline) {
|
||||
val proxyUri = VIAaaSConfig.backendProxy
|
||||
fun addProxyHandler(pipe: ChannelPipeline, proxyUri: URI?, socket: InetSocketAddress?) {
|
||||
if (proxyUri != null) {
|
||||
val socket = InetSocketAddress(AspirinServer.dnsResolver.resolve(proxyUri.host).get(), proxyUri.port)
|
||||
val user = proxyUri.userInfo?.substringBefore(':')
|
||||
val pass = proxyUri.userInfo?.substringAfter(':')
|
||||
val handler = when (proxyUri.scheme) {
|
||||
|
@ -8,12 +8,14 @@ import com.viaversion.aas.codec.FrameCodec
|
||||
import com.viaversion.aas.codec.MinecraftCodec
|
||||
import com.viaversion.aas.codec.packet.handshake.Handshake
|
||||
import com.viaversion.aas.codec.packet.status.StatusRequest
|
||||
import com.viaversion.aas.config.VIAaaSConfig
|
||||
import com.viaversion.aas.handler.ConnectionData
|
||||
import com.viaversion.aas.handler.MinecraftHandler
|
||||
import com.viaversion.aas.handler.addProxyHandler
|
||||
import com.viaversion.aas.send
|
||||
import com.viaversion.viaversion.api.protocol.packet.State
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
|
||||
import io.ktor.server.netty.*
|
||||
import io.netty.bootstrap.Bootstrap
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelFutureListener
|
||||
@ -21,52 +23,60 @@ import io.netty.channel.ChannelInitializer
|
||||
import io.netty.channel.ChannelOption
|
||||
import io.netty.handler.timeout.ReadTimeoutHandler
|
||||
import io.netty.resolver.NoopAddressResolverGroup
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.net.InetSocketAddress
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
object ProtocolDetector {
|
||||
private val SERVER_VER = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(30, TimeUnit.SECONDS)
|
||||
.expireAfterWrite(30, TimeUnit.SECONDS)
|
||||
.build<InetSocketAddress, CompletableFuture<ProtocolVersion>>(CacheLoader.from { address ->
|
||||
val future = CompletableFuture<ProtocolVersion>()
|
||||
try {
|
||||
val ch = Bootstrap()
|
||||
.group(AspirinServer.childLoop)
|
||||
.resolver(NoopAddressResolverGroup.INSTANCE)
|
||||
.channelFactory(channelSocketFactory(AspirinServer.childLoop))
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.IP_TOS, 0x18)
|
||||
.handler(object : ChannelInitializer<Channel>() {
|
||||
override fun initChannel(channel: Channel) {
|
||||
val data = ConnectionData(
|
||||
channel,
|
||||
state = ProtocolDetectionState(future),
|
||||
frontVer = -1
|
||||
)
|
||||
channel.pipeline().also { addProxyHandler(it) }
|
||||
.addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
.addLast("frame", FrameCodec())
|
||||
.addLast("mc", MinecraftCodec())
|
||||
.addLast("handler", MinecraftHandler(data, frontEnd = false))
|
||||
GlobalScope.launch {
|
||||
try {
|
||||
val proxyUri = VIAaaSConfig.backendProxy
|
||||
val proxySocket = if (proxyUri == null) null else {
|
||||
InetSocketAddress(AspirinServer.dnsResolver.resolve(proxyUri.host).suspendAwait(), proxyUri.port)
|
||||
}
|
||||
val ch = Bootstrap()
|
||||
.group(AspirinServer.childLoop)
|
||||
.resolver(NoopAddressResolverGroup.INSTANCE)
|
||||
.channelFactory(channelSocketFactory(AspirinServer.childLoop))
|
||||
.option(ChannelOption.TCP_NODELAY, true)
|
||||
.option(ChannelOption.IP_TOS, 0x18)
|
||||
.handler(object : ChannelInitializer<Channel>() {
|
||||
override fun initChannel(channel: Channel) {
|
||||
val data = ConnectionData(
|
||||
channel,
|
||||
state = ProtocolDetectionState(future),
|
||||
frontVer = -1
|
||||
)
|
||||
channel.pipeline().also { addProxyHandler(it, proxyUri, proxySocket) }
|
||||
.addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
|
||||
.addLast("frame", FrameCodec())
|
||||
.addLast("mc", MinecraftCodec())
|
||||
.addLast("handler", MinecraftHandler(data, frontEnd = false))
|
||||
}
|
||||
})
|
||||
.connect(address!!)
|
||||
ch.addListener(ChannelFutureListener {
|
||||
if (!it.isSuccess) {
|
||||
future.completeExceptionally(it.cause())
|
||||
} else {
|
||||
val handshake = Handshake()
|
||||
handshake.address = address.hostString
|
||||
handshake.port = address.port
|
||||
handshake.protocolId = -1
|
||||
handshake.nextState = State.STATUS
|
||||
send(ch.channel(), handshake)
|
||||
send(ch.channel(), StatusRequest(), flush = true)
|
||||
}
|
||||
})
|
||||
.connect(address!!)
|
||||
ch.addListener(ChannelFutureListener {
|
||||
if (!it.isSuccess) {
|
||||
future.completeExceptionally(it.cause())
|
||||
} else {
|
||||
val handshake = Handshake()
|
||||
handshake.address = address.hostString
|
||||
handshake.port = address.port
|
||||
handshake.protocolId = -1
|
||||
handshake.nextState = State.STATUS
|
||||
send(ch.channel(), handshake)
|
||||
send(ch.channel(), StatusRequest(), flush = true)
|
||||
}
|
||||
})
|
||||
} catch (throwable: Throwable) {
|
||||
future.completeExceptionally(throwable)
|
||||
} catch (throwable: Throwable) {
|
||||
future.completeExceptionally(throwable)
|
||||
}
|
||||
}
|
||||
future
|
||||
})
|
||||
|
@ -19,19 +19,22 @@ import io.netty.channel.socket.SocketChannel
|
||||
import io.netty.handler.proxy.ProxyHandler
|
||||
import io.netty.resolver.NoopAddressResolverGroup
|
||||
import kotlinx.coroutines.future.await
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import java.net.Inet4Address
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.URI
|
||||
|
||||
private suspend fun createBackChannel(
|
||||
handler: MinecraftHandler,
|
||||
socketAddr: InetSocketAddress,
|
||||
state: State,
|
||||
extraData: String?
|
||||
extraData: String?,
|
||||
proxyUri: URI?,
|
||||
proxyAddress: InetSocketAddress?
|
||||
): Channel {
|
||||
val loop = handler.data.frontChannel.eventLoop()
|
||||
val channel = Bootstrap()
|
||||
.handler(BackEndInit(handler.data))
|
||||
.handler(BackEndInit(handler.data, proxyUri, proxyAddress))
|
||||
.channelFactory(channelSocketFactory(loop.parent()))
|
||||
.group(loop)
|
||||
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, AspirinServer.bufferWaterMark)
|
||||
@ -64,23 +67,24 @@ private suspend fun createBackChannel(
|
||||
|
||||
private suspend fun autoDetectVersion(handler: MinecraftHandler, socketAddr: InetSocketAddress) {
|
||||
if (handler.data.backServerVer == -2) { // Auto
|
||||
var detectedProtocol: ProtocolVersion? = null
|
||||
try {
|
||||
val detectedProtocol = withTimeoutOrNull(10_000) {
|
||||
detectedProtocol = withTimeout(10_000) {
|
||||
ProtocolDetector.detectVersion(socketAddr).await()
|
||||
}
|
||||
|
||||
if (detectedProtocol != null
|
||||
&& detectedProtocol.version !in arrayOf(-1, -2)
|
||||
&& ProtocolVersion.isRegistered(detectedProtocol.version)
|
||||
) {
|
||||
handler.data.backServerVer = detectedProtocol.version
|
||||
} else {
|
||||
handler.data.backServerVer = 47 // fallback 1.8
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
mcLogger.warn("Failed to auto-detect version for $socketAddr: $e")
|
||||
mcLogger.warn("Failed to detect version of $socketAddr: $e")
|
||||
mcLogger.debug("Stacktrace: ", e)
|
||||
}
|
||||
|
||||
if (detectedProtocol != null
|
||||
&& detectedProtocol.version !in arrayOf(-1, -2)
|
||||
&& ProtocolVersion.isRegistered(detectedProtocol.version)
|
||||
) {
|
||||
handler.data.backServerVer = detectedProtocol.version
|
||||
} else {
|
||||
handler.data.backServerVer = 47 // fallback 1.8
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +105,12 @@ private suspend fun tryBackAddresses(
|
||||
throw StacklessException("Not allowed")
|
||||
}
|
||||
|
||||
createBackChannel(handler, socketAddr, state, extraData)
|
||||
val proxyUri = VIAaaSConfig.backendProxy
|
||||
val proxySocket = if (proxyUri == null) null else {
|
||||
InetSocketAddress(AspirinServer.dnsResolver.resolve(proxyUri.host).suspendAwait(), proxyUri.port)
|
||||
}
|
||||
|
||||
createBackChannel(handler, socketAddr, state, extraData, proxyUri, proxySocket)
|
||||
return // Finally it worked!
|
||||
} catch (e: Exception) {
|
||||
latestException = e
|
||||
|
Loading…
Reference in New Issue
Block a user