mirror of
https://github.com/ViaVersion/VIAaaS.git
synced 2024-11-21 11:55:15 +01:00
parent
fee83d594b
commit
4be71c01d2
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
.idea
|
||||
.gradle
|
||||
build
|
||||
config
|
||||
config
|
||||
logs
|
@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id("com.github.johnrengelman.shadow") version "6.1.0"
|
||||
application
|
||||
kotlin("jvm") version "1.3.72"
|
||||
kotlin("jvm") version "1.4.10"
|
||||
}
|
||||
|
||||
application {
|
||||
@ -27,19 +28,37 @@ dependencies {
|
||||
implementation("nl.matsv:viabackwards-all:3.1.1")
|
||||
implementation("de.gerrygames:viarewind-all:1.5.1")
|
||||
implementation("net.md-5:bungeecord-chat:1.16-R0.3")
|
||||
implementation("io.netty:netty-all:4.1.51.Final")
|
||||
implementation("io.netty:netty-all:4.1.53.Final")
|
||||
|
||||
implementation("org.apache.logging.log4j:log4j-core:2.13.3")
|
||||
implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.13.3")
|
||||
implementation("org.slf4j:slf4j-api:1.7.30")
|
||||
implementation("net.minecrell:terminalconsoleappender:1.2.0")
|
||||
implementation("org.jline:jline-terminal-jansi:3.12.1")
|
||||
|
||||
val ktorVersion = "1.4.1"
|
||||
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
|
||||
val ktorVersion = "1.4.0"
|
||||
|
||||
implementation("io.ktor:ktor-network-tls-certificates:$ktorVersion")
|
||||
implementation("io.ktor:ktor-server-netty:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-cio:$ktorVersion")
|
||||
implementation("io.ktor:ktor-client-gson:$ktorVersion")
|
||||
implementation("io.ktor:ktor-websockets:$ktorVersion")
|
||||
implementation("ch.qos.logback:logback-classic:1.2.3")
|
||||
testImplementation("io.ktor:ktor-server-test-host:$ktorVersion")
|
||||
}
|
||||
|
||||
val run: JavaExec by tasks
|
||||
run.standardInput = System.`in`
|
||||
run.standardInput = System.`in`
|
||||
|
||||
project.configurations.implementation.get().isCanBeResolved = true
|
||||
|
||||
|
||||
tasks {
|
||||
named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
|
||||
configurations = listOf(project.configurations.implementation.get())
|
||||
transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer::class.java)
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
@ -173,11 +173,6 @@ class CloudDecodeHandler(val info: UserConnection) : MessageToMessageDecoder<Byt
|
||||
transformedBuf.release()
|
||||
}
|
||||
}
|
||||
|
||||
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
|
||||
if (PipelineUtil.containsCause(cause, CancelCodecException::class.java)) return
|
||||
super.exceptionCaught(ctx, cause)
|
||||
}
|
||||
}
|
||||
|
||||
class CloudEncodeHandler(val info: UserConnection) : MessageToMessageEncoder<ByteBuf>() {
|
||||
@ -195,9 +190,4 @@ class CloudEncodeHandler(val info: UserConnection) : MessageToMessageEncoder<Byt
|
||||
transformedBuf.release()
|
||||
}
|
||||
}
|
||||
|
||||
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
|
||||
if (PipelineUtil.containsCause(cause, CancelCodecException::class.java)) return
|
||||
super.exceptionCaught(ctx, cause)
|
||||
}
|
||||
}
|
@ -6,12 +6,12 @@ import io.netty.buffer.ByteBufAllocator
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.SimpleChannelInboundHandler
|
||||
import org.slf4j.LoggerFactory
|
||||
import us.myles.ViaVersion.api.data.UserConnection
|
||||
import us.myles.ViaVersion.api.type.Type
|
||||
import us.myles.ViaVersion.packets.State
|
||||
import java.util.logging.Logger
|
||||
|
||||
val logger = Logger.getLogger("CloudHandler")
|
||||
val chLogger = LoggerFactory.getLogger("VIAaaS CloudHandler")
|
||||
|
||||
class CloudSideForwarder(val userConnection: UserConnection, var other: Channel?) : SimpleChannelInboundHandler<ByteBuf>() {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, msg: ByteBuf) {
|
||||
@ -22,7 +22,7 @@ class CloudSideForwarder(val userConnection: UserConnection, var other: Channel?
|
||||
|
||||
override fun channelInactive(ctx: ChannelHandlerContext) {
|
||||
super.channelInactive(ctx)
|
||||
logger.info(userConnection.channel?.remoteAddress().toString() + " was disconnected")
|
||||
chLogger.info(userConnection.channel?.remoteAddress().toString() + " was disconnected")
|
||||
other?.close()
|
||||
}
|
||||
|
||||
@ -45,7 +45,7 @@ class CloudSideForwarder(val userConnection: UserConnection, var other: Channel?
|
||||
fun disconnect(s: String) {
|
||||
if (userConnection.channel?.isActive != true) return
|
||||
|
||||
logger.info("Disconnecting " + userConnection.channel!!.remoteAddress() + ": " + s)
|
||||
chLogger.info("Disconnecting " + userConnection.channel!!.remoteAddress() + ": " + s)
|
||||
when (userConnection.protocolInfo!!.state) {
|
||||
State.LOGIN -> {
|
||||
val packet = ByteBufAllocator.DEFAULT.buffer()
|
||||
|
@ -5,6 +5,7 @@ import de.gerrygames.viarewind.api.ViaRewindPlatform
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.channel.DefaultEventLoop
|
||||
import nl.matsv.viabackwards.api.ViaBackwardsPlatform
|
||||
import org.slf4j.LoggerFactory
|
||||
import us.myles.ViaVersion.AbstractViaConfig
|
||||
import us.myles.ViaVersion.api.Via
|
||||
import us.myles.ViaVersion.api.ViaAPI
|
||||
@ -23,6 +24,7 @@ import us.myles.ViaVersion.commands.ViaCommandHandler
|
||||
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.libs.gson.JsonObject
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
@ -34,7 +36,7 @@ import java.util.concurrent.TimeUnit
|
||||
import java.util.logging.Logger
|
||||
|
||||
object CloudBackwards: ViaBackwardsPlatform {
|
||||
val log = Logger.getLogger("ViaBackwards")
|
||||
val log = LoggerWrapper(LoggerFactory.getLogger("ViaBackwards"))
|
||||
override fun getDataFolder() = File("config/viabackwards")
|
||||
override fun getLogger(): Logger = log
|
||||
override fun disable() {
|
||||
@ -42,7 +44,7 @@ object CloudBackwards: ViaBackwardsPlatform {
|
||||
}
|
||||
|
||||
object CloudRewind: ViaRewindPlatform {
|
||||
val log = Logger.getLogger("ViaRewind")
|
||||
val log = LoggerWrapper(LoggerFactory.getLogger("ViaRewind"))
|
||||
override fun getLogger(): Logger = log
|
||||
}
|
||||
|
||||
@ -119,7 +121,7 @@ object CloudPlatform : ViaPlatform<Unit> {
|
||||
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 = Logger.getLogger("ViaVersion")
|
||||
override fun getLogger(): Logger = LoggerWrapper(LoggerFactory.getLogger("ViaVersion"))
|
||||
override fun getConnectionManager(): ViaConnectionManager = connMan
|
||||
override fun getOnlinePlayers(): Array<ViaCommandSender> = arrayOf()
|
||||
override fun cancelTask(p0: TaskId?) {
|
||||
@ -170,13 +172,6 @@ class CloudTask(val obj: Future<*>) : TaskId {
|
||||
override fun getObject(): Any = obj
|
||||
}
|
||||
|
||||
object CloudConsoleSender : ViaCommandSender {
|
||||
override fun sendMessage(p0: String) = println(p0.replace(Regex("§."), ""))
|
||||
override fun getName(): String = "VIAaaS console"
|
||||
override fun getUUID(): UUID = UUID.fromString(name)
|
||||
override fun hasPermission(p0: String): Boolean = true
|
||||
}
|
||||
|
||||
object CloudVersionProvider : VersionProvider() {
|
||||
override fun getServerProtocol(connection: UserConnection): Int {
|
||||
val data = connection.get(CloudData::class.java)
|
||||
|
@ -191,12 +191,18 @@ object CloudTailProtocol : SimpleProtocol() {
|
||||
.generatePublic(X509EncodedKeySpec(it.get(Type.BYTE_ARRAY_PRIMITIVE, 0)))
|
||||
data.backToken = it.get(Type.BYTE_ARRAY_PRIMITIVE, 1)
|
||||
|
||||
val id = "VIAaaS" + ByteArray(10).let {
|
||||
secureRandom.nextBytes(it)
|
||||
Base64.getEncoder().withoutPadding().encodeToString(it)
|
||||
// https://developer.mozilla.org/en-US/docs/Glossary/Base64 133% of original
|
||||
}
|
||||
// We'll use non-vanilla server id, public key size and token size
|
||||
it.set(Type.STRING, 0, "VIAaaS")
|
||||
it.set(Type.STRING, 0, id)
|
||||
it.set(Type.BYTE_ARRAY_PRIMITIVE, 0, mcCryptoKey.public.encoded)
|
||||
val token = ByteArray(16)
|
||||
secureRandom.nextBytes(token)
|
||||
data.frontToken = token
|
||||
data.frontId = id
|
||||
it.set(Type.BYTE_ARRAY_PRIMITIVE, 1, token.clone())
|
||||
}
|
||||
}
|
||||
@ -233,7 +239,7 @@ object CloudTailProtocol : SimpleProtocol() {
|
||||
wrapper.user().channel!!.pipeline().get(CloudEncryptor::class.java).cipher = aesEn
|
||||
wrapper.user().channel!!.pipeline().get(CloudDecryptor::class.java).cipher = aesDe
|
||||
|
||||
val frontHash = generateServerHash("VIAaaS", secret, mcCryptoKey.public)
|
||||
val frontHash = generateServerHash(data.frontId!!, secret, mcCryptoKey.public)
|
||||
|
||||
val backKey = ByteArray(16)
|
||||
secureRandom.nextBytes(backKey)
|
||||
@ -333,5 +339,6 @@ data class CloudData(val userConnection: UserConnection,
|
||||
var backPublicKey: PublicKey? = null,
|
||||
var backToken: ByteArray? = null,
|
||||
var frontToken: ByteArray? = null,
|
||||
var frontLoginName: String? = null
|
||||
var frontLoginName: String? = null,
|
||||
var frontId: String? = null
|
||||
) : StoredObject(userConnection)
|
@ -14,14 +14,21 @@ import io.netty.channel.ChannelOption
|
||||
import io.netty.channel.nio.NioEventLoopGroup
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||
import io.netty.util.concurrent.Future
|
||||
import net.minecrell.terminalconsole.SimpleTerminalConsole
|
||||
import org.slf4j.LoggerFactory
|
||||
import us.myles.ViaVersion.ViaManager
|
||||
import us.myles.ViaVersion.api.Via
|
||||
import us.myles.ViaVersion.api.command.ViaCommandSender
|
||||
import us.myles.ViaVersion.api.data.MappingDataLoader
|
||||
import us.myles.ViaVersion.api.protocol.ProtocolVersion
|
||||
import us.myles.ViaVersion.util.Config
|
||||
import java.io.File
|
||||
import java.net.InetAddress
|
||||
import java.security.KeyPairGenerator
|
||||
import java.util.*
|
||||
|
||||
var runningServer = true
|
||||
var viaaasLogger = LoggerFactory.getLogger("VIAaaS")
|
||||
|
||||
val httpClient = HttpClient {
|
||||
defaultRequest {
|
||||
@ -62,22 +69,12 @@ fun main(args: Array<String>) {
|
||||
.childOption(ChannelOption.IP_TOS, 0x18)
|
||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||
.bind(InetAddress.getByName(VIAaaSConfig.bindAddress), VIAaaSConfig.port)
|
||||
println("Binded minecraft into " + future.sync().channel().localAddress())
|
||||
viaaasLogger.info("Binded minecraft into " + future.sync().channel().localAddress())
|
||||
|
||||
val ktorServer = embeddedServer(Netty, commandLineEnvironment(args)) {}.start(false)
|
||||
|
||||
loop@ while (true) {
|
||||
try {
|
||||
val cmd = readLine()?.trim()?.split(" ")
|
||||
when (cmd?.get(0)?.toLowerCase()) {
|
||||
"stop", "end" -> break@loop
|
||||
"viaversion", "viaver" -> Via.getManager().commandHandler.onCommand(CloudConsoleSender, cmd.subList(1, cmd.size)
|
||||
.toTypedArray())
|
||||
else -> println("unknown command")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
while (runningServer) {
|
||||
VIAaaSConsole().start()
|
||||
}
|
||||
|
||||
ktorServer.stop(1000, 1000)
|
||||
@ -88,6 +85,55 @@ fun main(args: Array<String>) {
|
||||
Via.getManager().destroy()
|
||||
}
|
||||
|
||||
class VIAaaSConsole : SimpleTerminalConsole(), ViaCommandSender {
|
||||
val commands = hashMapOf<String, (String, Array<String>) -> Unit>()
|
||||
override fun isRunning(): Boolean = runningServer
|
||||
|
||||
init {
|
||||
commands["stop"] = { _, _ -> this.shutdown() }
|
||||
commands["end"] = commands["stop"]!!
|
||||
commands["viaversion"] = { _, args ->
|
||||
Via.getManager().commandHandler.onCommand(this, args)
|
||||
}
|
||||
commands["viaver"] = commands["viaversion"]!!
|
||||
commands["vvcloud"] = commands["viaversion"]!!
|
||||
commands["help"] = { _, _ ->
|
||||
sendMessage(commands.keys.toString())
|
||||
}
|
||||
commands["?"] = commands["help"]!!
|
||||
}
|
||||
|
||||
override fun runCommand(command: String) {
|
||||
val cmd = command.split(" ")
|
||||
try {
|
||||
val alias = cmd[0].toLowerCase()
|
||||
val args = cmd.subList(1, cmd.size).toTypedArray()
|
||||
val runnable = commands[alias]
|
||||
if (runnable == null) {
|
||||
sendMessage("unknown command, try 'help'")
|
||||
} else {
|
||||
runnable(alias, args)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
sendMessage("Error running command: $e")
|
||||
}
|
||||
}
|
||||
|
||||
override fun shutdown() {
|
||||
viaaasLogger.info("Shutting down...")
|
||||
runningServer = false
|
||||
}
|
||||
|
||||
|
||||
override fun sendMessage(p0: String) {
|
||||
LoggerFactory.getLogger(this.name).info(p0)
|
||||
}
|
||||
|
||||
override fun hasPermission(p0: String): Boolean = true
|
||||
override fun getUUID(): UUID = UUID.fromString(name)
|
||||
override fun getName(): String = "VIAaaS Console"
|
||||
}
|
||||
|
||||
fun Application.mainWeb() {
|
||||
ViaWebApp().apply { main() }
|
||||
}
|
||||
|
@ -16,6 +16,8 @@ import io.ktor.routing.*
|
||||
import io.ktor.websocket.*
|
||||
import kotlinx.coroutines.channels.consumeEach
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.slf4j.event.Level
|
||||
import java.net.URLEncoder
|
||||
import java.time.Duration
|
||||
import java.util.*
|
||||
@ -29,11 +31,14 @@ import kotlin.collections.set
|
||||
// todo https://minecraft.id/documentation
|
||||
|
||||
val viaWebServer = WebDashboardServer()
|
||||
val webLogger = LoggerFactory.getLogger("VIAaaS Web")
|
||||
|
||||
class ViaWebApp {
|
||||
fun Application.main() {
|
||||
install(DefaultHeaders)
|
||||
install(CallLogging)
|
||||
install(CallLogging) {
|
||||
level = Level.INFO
|
||||
}
|
||||
install(WebSockets) {
|
||||
pingPeriod = Duration.ofMinutes(1)
|
||||
}
|
||||
@ -94,7 +99,7 @@ class WebDashboardServer {
|
||||
.expireAfterWrite(30, TimeUnit.SECONDS)
|
||||
.build<String, CompletableFuture<Void>>(CacheLoader.from { _ -> CompletableFuture() })
|
||||
|
||||
suspend fun connected(ws: WebSocketSession) {
|
||||
suspend fun connected(ws: WebSocketServerSession) {
|
||||
val loginState = WebLogin()
|
||||
val client = WebClient(this, ws, loginState)
|
||||
clients[ws] = client
|
||||
@ -120,7 +125,7 @@ class WebDashboardServer {
|
||||
|
||||
|
||||
data class WebClient(val server: WebDashboardServer,
|
||||
val ws: WebSocketSession,
|
||||
val ws: WebSocketServerSession,
|
||||
val state: WebState,
|
||||
val listenedIds: MutableSet<UUID> = mutableSetOf())
|
||||
|
||||
@ -138,7 +143,7 @@ class WebLogin : WebState {
|
||||
}
|
||||
|
||||
override suspend fun onMessage(webClient: WebClient, msg: String) {
|
||||
val obj = Gson().fromJson<JsonObject>(msg, JsonObject::class.java)
|
||||
val obj = Gson().fromJson(msg, JsonObject::class.java)
|
||||
|
||||
when (obj.getAsJsonPrimitive("action").asString) {
|
||||
"minecraft_id_login" -> {
|
||||
@ -151,7 +156,6 @@ class WebLogin : WebState {
|
||||
encodeInQuery = false) {
|
||||
}
|
||||
|
||||
|
||||
if (check.getAsJsonPrimitive("valid").asBoolean) {
|
||||
val token = UUID.randomUUID()
|
||||
val mcIdUser = check.get("username").asString
|
||||
@ -160,8 +164,11 @@ class WebLogin : WebState {
|
||||
webClient.server.loginTokens.put(token, uuid)
|
||||
webClient.ws.send("""{"action": "minecraft_id_result", "success": true,
|
||||
| "username": "$mcIdUser", "uuid": "$uuid", "token": "$token"}""".trimMargin())
|
||||
|
||||
webLogger.info("${webClient.ws.call.request.origin} generated a token for account $mcIdUser $uuid")
|
||||
} else {
|
||||
webClient.ws.send("""{"action": "minecraft_id_result", "success": false}""")
|
||||
webLogger.info("${webClient.ws.call.request.origin} failed to generated a token for account $username")
|
||||
}
|
||||
}
|
||||
"listen_login_requests" -> {
|
||||
@ -172,8 +179,11 @@ class WebLogin : WebState {
|
||||
webClient.listenedIds.add(user)
|
||||
webClient.server.listeners.computeIfAbsent(user) { Collections.newSetFromMap(ConcurrentHashMap()) }
|
||||
.add(webClient)
|
||||
|
||||
webLogger.info("${webClient.ws.call.request.origin} is listening for logins for $user")
|
||||
} else {
|
||||
webClient.ws.send("""{"action": "listen_login_requests_result", "token": "$token", "success": false}""")
|
||||
webLogger.info("${webClient.ws.call.request.origin} failed token for $user")
|
||||
}
|
||||
}
|
||||
"session_hash_response" -> {
|
||||
|
23
src/main/resources/log4j2.xml
Normal file
23
src/main/resources/log4j2.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- parts stolen from https://github.com/GeyserMC/Geyser/blob/4a425df20d1b4fa3cd614910a269f3d3f2609535/bootstrap/standalone/src/main/resources/log4j2.xml -->
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<TerminalConsole name="TerminalConsole">
|
||||
<PatternLayout
|
||||
pattern="%d{HH:mm:ss} %style{%highlight{%level}{FATAL=red dark, ERROR=red, WARN=yellow bright, INFO=cyan bright, DEBUG=green, TRACE=white}} [%thread] [%logger] %minecraftFormatting{%msg}%n"/>
|
||||
</TerminalConsole>
|
||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||
<PatternLayout pattern="%d{yyy-MM-dd HH:mm:ss.SSS} [%t] [%logger] %level{length=1} - %msg%n"/>
|
||||
<Policies>
|
||||
<TimeBasedTriggeringPolicy/>
|
||||
<OnStartupTriggeringPolicy/>
|
||||
</Policies>
|
||||
</RollingRandomAccessFile>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Root level="INFO">
|
||||
<AppenderRef ref="TerminalConsole"/>
|
||||
<AppenderRef ref="File"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
Loading…
Reference in New Issue
Block a user