closes #5 closes #4, add log4j and terminal console

This commit is contained in:
creeper123123321 2020-10-30 12:00:16 -03:00
parent fee83d594b
commit 4be71c01d2
9 changed files with 144 additions and 53 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
.idea
.gradle
build
config
config
logs

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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() }
}

View File

@ -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" -> {

View 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>