From 8b02a8f1ba92ca907367ec492fdf9427de80c19b Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Thu, 25 Aug 2022 13:27:52 +1200 Subject: [PATCH 1/8] Removed unused components --- .../com/jacobtread/relay/blaze/Components.kt | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/kotlin/com/jacobtread/relay/blaze/Components.kt b/src/main/kotlin/com/jacobtread/relay/blaze/Components.kt index a1349c2..3789866 100644 --- a/src/main/kotlin/com/jacobtread/relay/blaze/Components.kt +++ b/src/main/kotlin/com/jacobtread/relay/blaze/Components.kt @@ -1,29 +1,14 @@ package com.jacobtread.relay.blaze -@Suppress("unused") object Components { const val AUTHENTICATION = 0x1 - const val EXAMPLE = 0x3 const val GAME_MANAGER = 0x4 const val REDIRECTOR = 0x5 - const val PLAY_GROUPS = 0x6 const val STATS = 0x7 const val UTIL = 0x9 - const val CENSUS_DATA = 0xA - const val CLUBS = 0xB - const val GAME_REPORT_LEGACY = 0xC - const val LEAGUE = 0xD - const val MAIL = 0xE const val MESSAGING = 0xF - const val LOCKER = 0x14 - const val ROOMS = 0x15 - const val TOURNAMENTS = 0x17 - const val COMMERCE_INFO = 0x18 const val ASSOCIATION_LISTS = 0x19 - const val GPS_CONTENT_CONTROLLER = 0x1B const val GAME_REPORTING = 0x1C const val DYNAMIC_FILTER = 0x7D0 - const val RSP = 0x801 const val USER_SESSIONS = 0x7802 - } From 56ba2402913e409059a4db09e122ef06d3358c91 Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Thu, 25 Aug 2022 13:28:13 +1200 Subject: [PATCH 2/8] Bump version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 48b434e..373892b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,7 @@ kotlin.code.style=official ksp.incremental=false # The version of this software. This is compiled into the constants -serverVersion=1.0.5 +serverVersion=1.0.6 # This is the name of the jar file that will be produced when app:shadowJar is # run. Note: If you are planning on using this in a docker image you will need From 6a5c14e9e6df31fda1a0903cbd3d323f05f16df7 Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Thu, 25 Aug 2022 16:43:00 +1200 Subject: [PATCH 3/8] Omit telemetry info from POST_AUTH --- .../relay/sessions/handlers/UtilHandlers.kt | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt b/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt index d285651..78eae2d 100644 --- a/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt +++ b/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt @@ -202,21 +202,6 @@ fun Session.handlePostAuth(packet: Packet) { // telemetryAddress = "reports.tools.gos.ea.com:9988" // tickerAddress = "waleu2.tools.gos.ea.com:8999" - +group("TELE") { - text("ADRS", "127.0.0.1") // Server Address - number("ANON", 0) - text("DISA", "**") - text("FILT", "-UION/****") // Telemetry filter? - number("LOC", 1701725253) - text("NOOK", "US,CA,MX") - number("PORT", 9988) - number("SDLY", 15000) - text("SESS", "JMhnT9dXSED") - text("SKEY", "") - number("SPCT", 0x4B) - text("STIM", "") - } - +group("TICK") { text("ADRS", "127.0.0.1") number("port", 9988) From c7fa4502d02a45c07c49f118d8ba4a3c152954b1 Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Thu, 25 Aug 2022 17:37:28 +1200 Subject: [PATCH 4/8] Temporary servers for debugging and intercepting --- src/main/kotlin/com/jacobtread/relay/App.kt | 6 + .../com/jacobtread/relay/data/Constants.kt | 2 +- .../jacobtread/relay/http/routes/QOSRoutes.kt | 3 +- .../relay/servers/PlayerSyncService.kt | 133 ++++++++++++++++++ .../com/jacobtread/relay/servers/QOSServer.kt | 84 +++++++++++ .../relay/servers/TelemetryServer.kt | 133 ++++++++++++++++++ .../relay/sessions/handlers/UtilHandlers.kt | 18 +++ 7 files changed, 377 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt create mode 100644 src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt create mode 100644 src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt diff --git a/src/main/kotlin/com/jacobtread/relay/App.kt b/src/main/kotlin/com/jacobtread/relay/App.kt index 3ce94a1..60fd393 100644 --- a/src/main/kotlin/com/jacobtread/relay/App.kt +++ b/src/main/kotlin/com/jacobtread/relay/App.kt @@ -4,9 +4,12 @@ package com.jacobtread.relay import com.jacobtread.relay.http.startHttpServer import com.jacobtread.relay.servers.startMainServer +import com.jacobtread.relay.servers.startQOSServer import com.jacobtread.relay.servers.startRedirector +import com.jacobtread.relay.servers.startTelemetryServer import com.jacobtread.relay.utils.logging.Logger import io.netty.channel.nio.NioEventLoopGroup +import startSyncServer import java.util.concurrent.CompletableFuture as Future fun main() { @@ -19,6 +22,9 @@ fun main() { startRedirector(bossGroup, workerGroup), startHttpServer(bossGroup, workerGroup), startMainServer(bossGroup, workerGroup), + startSyncServer(bossGroup, workerGroup), + startTelemetryServer(bossGroup, workerGroup), + startQOSServer(bossGroup, workerGroup) ).get() System.gc() // Cleanup after initialization diff --git a/src/main/kotlin/com/jacobtread/relay/data/Constants.kt b/src/main/kotlin/com/jacobtread/relay/data/Constants.kt index 1666bf3..a263912 100644 --- a/src/main/kotlin/com/jacobtread/relay/data/Constants.kt +++ b/src/main/kotlin/com/jacobtread/relay/data/Constants.kt @@ -8,7 +8,7 @@ package com.jacobtread.relay.data * @constructor Create empty Constants */ object Constants { - const val RELAY_VERSION = "1.0.5" + const val RELAY_VERSION = "1.0.6" const val MYSQL_VERSION = "8.0.30" const val SQLITE_VERSION = "3.36.0.3" } diff --git a/src/main/kotlin/com/jacobtread/relay/http/routes/QOSRoutes.kt b/src/main/kotlin/com/jacobtread/relay/http/routes/QOSRoutes.kt index 2d18449..0fc5ee7 100644 --- a/src/main/kotlin/com/jacobtread/relay/http/routes/QOSRoutes.kt +++ b/src/main/kotlin/com/jacobtread/relay/http/routes/QOSRoutes.kt @@ -9,7 +9,8 @@ fun RoutingGroup.routeQOS() { textNode("numprobes", 0) textNode("qosport", 17499) // This is a port textNode("probesize", 0) - textNode("qosip", 2733913518) // This is a encoded ip address + // 162.244.53.174 + textNode("qosip", 2733913518) textNode("requestid", 1) textNode("reqsecret", 0) } diff --git a/src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt b/src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt new file mode 100644 index 0000000..684f474 --- /dev/null +++ b/src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt @@ -0,0 +1,133 @@ +package com.jacobtread.relay.servers + +import com.jacobtread.blaze.logging.PacketLogger +import com.jacobtread.relay.Environment +import com.jacobtread.relay.utils.logging.Logger +import io.netty.bootstrap.Bootstrap +import io.netty.bootstrap.ServerBootstrap +import io.netty.buffer.ByteBuf +import io.netty.channel.Channel +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.ChannelInboundHandlerAdapter +import io.netty.channel.ChannelInitializer +import io.netty.channel.nio.NioEventLoopGroup +import io.netty.channel.socket.nio.NioServerSocketChannel +import io.netty.channel.socket.nio.NioSocketChannel +import java.io.IOException +import java.util.concurrent.CompletableFuture + +/** + * startRedirector + * + * @param bossGroup The netty boss event loop group + * @param workerGroup The netty worker event loop group + */ +fun startTelemetryServer(bossGroup: NioEventLoopGroup, workerGroup: NioEventLoopGroup): CompletableFuture<Void> { + val startupFuture = CompletableFuture<Void>() + try { + val listenPort = 9988 + ServerBootstrap() + .group(bossGroup, workerGroup) + .channel(NioServerSocketChannel::class.java) + .childHandler(object : ChannelInitializer<Channel>() { + override fun initChannel(ch: Channel) { + val remoteAddress = ch.remoteAddress() + Logger.debug("Connection at $remoteAddress to telemetry Server") + PacketLogger.setEnabled(ch, true) + ch.pipeline().addLast(TelemetryHandler(ch)) + } + }) + .bind(listenPort) + .addListener { + Logger.info("Started Telemetry on port 9988") + startupFuture.complete(null) + } + } catch (e: IOException) { + val reason = e.message ?: e.javaClass.simpleName + Logger.fatal("Unable to start telemetry server: $reason") + } + return startupFuture +} + +class TelemetryHandler(val clientChannel: Channel) : ChannelInboundHandlerAdapter() { + + private var sessionId: Int = -1 + private fun createServerChannel(): Channel { + val channelFuture = Bootstrap() + .group(NioEventLoopGroup()) + .channel(NioSocketChannel::class.java) + .handler(OfficialHandler()) + .connect("159.153.235.32", 9988) + .sync() + return channelFuture.channel() + } + private var serverChannel: Channel = createServerChannel() + + inner class OfficialHandler : ChannelInboundHandlerAdapter() { + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is ByteBuf) { + Logger.info("[TELEMETRY] [SERVER] Sent bytes ${msg.readableBytes()}") + } + clientChannel.writeAndFlush(msg) + } + } + + private fun decodeTLM3(value: String): String { + + val telemtryKey = "The truth is back in style." + val keyChars = telemtryKey.toCharArray() + val startIndex = value.indexOf('-') + val out = StringBuilder() + if (startIndex != -1) { + val start = startIndex + 1 + val chars = value.toCharArray() + for (i in start until value.length) { + val charAt = chars[i] + val newChar = keyChars[(i - start) % telemtryKey.length] + val xorValue = charAt.code xor newChar.code + if (xorValue <= 128) { + out.append(xorValue.toChar()) + } else { + out.append((newChar.code xor (charAt.code - 128)).toChar()) + } + } + } + return out.toString() + } + + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is ByteBuf) { + Logger.info("[TELEMETRY] [CLIENT] Sent bytes ${msg.readableBytes()}") + + msg.skipBytes(10) // Skip Heading + val text = msg.readCharSequence(msg.readableBytes(), Charsets.UTF_8) + val lines = text.split('\n') + val dataMap = HashMap<String, String>() + lines.forEach { line -> + val parts = line.split('=', limit = 2) + if (parts.size == 2) { + dataMap[parts[0]] = parts[1] + } + } + + val auth = dataMap["AUTH"] + if (auth != null) { + sessionId = auth.toInt() + } + val tlm3 = dataMap["TLM3"] + if (tlm3 != null) { + val decoded = decodeTLM3(tlm3).replace('/', '\n') + Logger.info("Telemetry TLM3: $decoded") + } + + + Logger.info(dataMap.toString()) + Logger.debug("TELEMETRY DATA: $text") + } + if (serverChannel.isOpen) { + serverChannel.writeAndFlush(msg) + } else { + serverChannel = createServerChannel() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt b/src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt new file mode 100644 index 0000000..92767a9 --- /dev/null +++ b/src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt @@ -0,0 +1,84 @@ +package com.jacobtread.relay.servers + +import com.jacobtread.blaze.logging.PacketLogger +import com.jacobtread.relay.Environment +import com.jacobtread.relay.utils.logging.Logger +import io.netty.bootstrap.Bootstrap +import io.netty.bootstrap.ServerBootstrap +import io.netty.buffer.ByteBuf +import io.netty.channel.Channel +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.ChannelInboundHandlerAdapter +import io.netty.channel.ChannelInitializer +import io.netty.channel.nio.NioEventLoopGroup +import io.netty.channel.socket.nio.NioServerSocketChannel +import io.netty.channel.socket.nio.NioSocketChannel +import java.io.IOException +import java.util.concurrent.CompletableFuture + +/** + * startRedirector + * + * @param bossGroup The netty boss event loop group + * @param workerGroup The netty worker event loop group + */ +fun startQOSServer(bossGroup: NioEventLoopGroup, workerGroup: NioEventLoopGroup): CompletableFuture<Void> { + val startupFuture = CompletableFuture<Void>() + try { + val listenPort = 17499 + ServerBootstrap() + .group(bossGroup, workerGroup) + .channel(NioServerSocketChannel::class.java) + .childHandler(object : ChannelInitializer<Channel>() { + override fun initChannel(ch: Channel) { + val remoteAddress = ch.remoteAddress() + Logger.debug("Connection at $remoteAddress to QOS Server") + PacketLogger.setEnabled(ch, true) + ch.pipeline().addLast(QOSHandler(ch)) + } + }) + .bind(listenPort) + .addListener { + Logger.info("Started QOS on port 17499") + startupFuture.complete(null) + } + } catch (e: IOException) { + val reason = e.message ?: e.javaClass.simpleName + Logger.fatal("Unable to start telemetry server: $reason") + } + return startupFuture +} + +class QOSHandler(val clientChannel: Channel) : ChannelInboundHandlerAdapter() { + + private fun createServerChannel(): Channel { + val channelFuture = Bootstrap() + .group(NioEventLoopGroup()) + .channel(NioSocketChannel::class.java) + .handler(OfficialHandler()) + .connect("162.244.53.174", 17499) + .sync() + return channelFuture.channel() + } + private var serverChannel: Channel = createServerChannel() + + inner class OfficialHandler : ChannelInboundHandlerAdapter() { + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is ByteBuf) { + Logger.info("[QOSSERVER] [SERVER] Sent bytes ${msg.readableBytes()}") + } + clientChannel.writeAndFlush(msg) + } + } + + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is ByteBuf) { + Logger.info("[QOSSERVER] [CLIENT] Sent bytes ${msg.readableBytes()}") + } + if (serverChannel.isOpen) { + serverChannel.writeAndFlush(msg) + } else { + serverChannel = createServerChannel() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt b/src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt new file mode 100644 index 0000000..684f474 --- /dev/null +++ b/src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt @@ -0,0 +1,133 @@ +package com.jacobtread.relay.servers + +import com.jacobtread.blaze.logging.PacketLogger +import com.jacobtread.relay.Environment +import com.jacobtread.relay.utils.logging.Logger +import io.netty.bootstrap.Bootstrap +import io.netty.bootstrap.ServerBootstrap +import io.netty.buffer.ByteBuf +import io.netty.channel.Channel +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.ChannelInboundHandlerAdapter +import io.netty.channel.ChannelInitializer +import io.netty.channel.nio.NioEventLoopGroup +import io.netty.channel.socket.nio.NioServerSocketChannel +import io.netty.channel.socket.nio.NioSocketChannel +import java.io.IOException +import java.util.concurrent.CompletableFuture + +/** + * startRedirector + * + * @param bossGroup The netty boss event loop group + * @param workerGroup The netty worker event loop group + */ +fun startTelemetryServer(bossGroup: NioEventLoopGroup, workerGroup: NioEventLoopGroup): CompletableFuture<Void> { + val startupFuture = CompletableFuture<Void>() + try { + val listenPort = 9988 + ServerBootstrap() + .group(bossGroup, workerGroup) + .channel(NioServerSocketChannel::class.java) + .childHandler(object : ChannelInitializer<Channel>() { + override fun initChannel(ch: Channel) { + val remoteAddress = ch.remoteAddress() + Logger.debug("Connection at $remoteAddress to telemetry Server") + PacketLogger.setEnabled(ch, true) + ch.pipeline().addLast(TelemetryHandler(ch)) + } + }) + .bind(listenPort) + .addListener { + Logger.info("Started Telemetry on port 9988") + startupFuture.complete(null) + } + } catch (e: IOException) { + val reason = e.message ?: e.javaClass.simpleName + Logger.fatal("Unable to start telemetry server: $reason") + } + return startupFuture +} + +class TelemetryHandler(val clientChannel: Channel) : ChannelInboundHandlerAdapter() { + + private var sessionId: Int = -1 + private fun createServerChannel(): Channel { + val channelFuture = Bootstrap() + .group(NioEventLoopGroup()) + .channel(NioSocketChannel::class.java) + .handler(OfficialHandler()) + .connect("159.153.235.32", 9988) + .sync() + return channelFuture.channel() + } + private var serverChannel: Channel = createServerChannel() + + inner class OfficialHandler : ChannelInboundHandlerAdapter() { + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is ByteBuf) { + Logger.info("[TELEMETRY] [SERVER] Sent bytes ${msg.readableBytes()}") + } + clientChannel.writeAndFlush(msg) + } + } + + private fun decodeTLM3(value: String): String { + + val telemtryKey = "The truth is back in style." + val keyChars = telemtryKey.toCharArray() + val startIndex = value.indexOf('-') + val out = StringBuilder() + if (startIndex != -1) { + val start = startIndex + 1 + val chars = value.toCharArray() + for (i in start until value.length) { + val charAt = chars[i] + val newChar = keyChars[(i - start) % telemtryKey.length] + val xorValue = charAt.code xor newChar.code + if (xorValue <= 128) { + out.append(xorValue.toChar()) + } else { + out.append((newChar.code xor (charAt.code - 128)).toChar()) + } + } + } + return out.toString() + } + + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + if (msg is ByteBuf) { + Logger.info("[TELEMETRY] [CLIENT] Sent bytes ${msg.readableBytes()}") + + msg.skipBytes(10) // Skip Heading + val text = msg.readCharSequence(msg.readableBytes(), Charsets.UTF_8) + val lines = text.split('\n') + val dataMap = HashMap<String, String>() + lines.forEach { line -> + val parts = line.split('=', limit = 2) + if (parts.size == 2) { + dataMap[parts[0]] = parts[1] + } + } + + val auth = dataMap["AUTH"] + if (auth != null) { + sessionId = auth.toInt() + } + val tlm3 = dataMap["TLM3"] + if (tlm3 != null) { + val decoded = decodeTLM3(tlm3).replace('/', '\n') + Logger.info("Telemetry TLM3: $decoded") + } + + + Logger.info(dataMap.toString()) + Logger.debug("TELEMETRY DATA: $text") + } + if (serverChannel.isOpen) { + serverChannel.writeAndFlush(msg) + } else { + serverChannel = createServerChannel() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt b/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt index 78eae2d..1d12fc5 100644 --- a/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt +++ b/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt @@ -12,6 +12,24 @@ import com.jacobtread.relay.sessions.Session import com.jacobtread.relay.utils.logging.Logger import com.jacobtread.relay.utils.unixTimeSeconds +@PacketHandler(Components.UTIL, Commands.GET_TELEMETRY_SERVER) +fun Session.handleGetTelemetryServer(packet:Packet) { + push(packet.respond { + text("ADRS", Environment.externalAddress) + number("ANON", 0) + text("DISA", "AD,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AW,AX,AZ,BA,BB,BD,BF,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CC,CD,CF,CG,CI,CK,CL,CM,CN,CO,CR,CU,CV,CX,DJ,DM,DO,DZ,EC,EG,EH,ER,ET,FJ,FK,FM,FO,GA,GD,GE,GF,GG,GH,GI,GL,GM,GN,GP,GQ,GS,GT,GU,GW,GY,HM,HN,HT,ID,IL,IM,IN,IO,IQ,IR,IS,JE,JM,JO,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,LY,MA,MC,MD,ME,MG,MH,ML,MM,MN,MO,MP,MQ,MR,MS,MU,MV,MW,MY,MZ,NA,NC,NE,NF,NG,NI,NP,NR,NU,OM,PA,PE,PF,PG,PH,PK,PM,PN,PS,PW,PY,QA,RE,RS,RW,SA,SB,SC,SD,SG,SH,SJ,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TL,TM,TN,TO,TT,TV,TZ,UA,UG,UM,UY,UZ,VA,VC,VE,VG,VN,VU,WF,WS,YE,YT,ZM,ZW,ZZ") + text("FILT", "-UION/****") + number("LOC", 0x656e5553) + text("NOOK", "US,CA,MX") + number("PORT", 9988) + number("SDLY", 15000) + text("SESS", "Evi8itOCVpD") + text("SKEY", sessionId.toString()) + number("SPCT", 75) + text("STIM") + }) +} + /** * Handles the pre authentication packet this includes information about the * client such as location, version, platform, etc. This response with information From 014f3cb9f3f89cecd0de774dbc78e66bf2d7e652 Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Sat, 27 Aug 2022 15:03:32 +1200 Subject: [PATCH 5/8] Fixed async bugs --- .../relay/database/models/Player.kt | 67 ++++++++++--------- .../relay/database/tables/PlayersTable.kt | 16 +++-- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/main/kotlin/com/jacobtread/relay/database/models/Player.kt b/src/main/kotlin/com/jacobtread/relay/database/models/Player.kt index 28faf55..d741ede 100644 --- a/src/main/kotlin/com/jacobtread/relay/database/models/Player.kt +++ b/src/main/kotlin/com/jacobtread/relay/database/models/Player.kt @@ -118,38 +118,43 @@ data class Player( } } + class SettingsMapLoader(private val player: Player) { + private val out = LinkedHashMap<String, String>() + + fun load(): Future<Map<String, String>> { + val classesFuture = PlayerClassesTable.getByPlayer(player) + .thenApply { classes -> classes.forEach { out[it.getKey()] = it.toEncoded() } } + val charactersFuture = PlayerCharactersTable.getByPlayer(player) + .thenApply { characters -> characters.forEach { out[it.getKey()] = it.toEncoded() } } + val settingsBase = StringBuilder("20;4;") + .append(player.credits).append(";-1;0;") + .append(player.creditsSpent).append(";0;") + .append(player.gamesPlayed).append(';') + .append(player.secondsPlayed).append(";0;") + .append(player.inventory) + .toString() + return Future.allOf(classesFuture, charactersFuture) + .thenApply { + player.faceCodes?.apply { out["FaceCodes"] = this } + player.newItem?.apply { out["NewItem"] = this } + out["csreward"] = player.csReward.toString() + + player.completion?.apply { out["Completion"] = this } + player.progress?.apply { out["Progress"] = this } + player.cscompletion?.apply { out["cscompletion"] = this } + player.cstimestamps1?.apply { out["cstimestamps"] = this } + player.cstimestamps2?.apply { out["cstimestamps2"] = this } + player.cstimestamps3?.apply { out["cstimestamps3"] = this } + out["Base"] = settingsBase + out + } + } + + } + fun createSettingsMap(): Future<Map<String, String>> { - val out = LinkedHashMap<String, String>() - val classesFuture = PlayerClassesTable.getByPlayer(this) - .thenApply { classes -> - classes.forEach { out[it.getKey()] = it.toEncoded() } - } - val charactersFuture = PlayerCharactersTable.getByPlayer(this) - .thenApply { characters -> - characters.forEach { out[it.getKey()] = it.toEncoded() } - } - val settingsBase = StringBuilder("20;4;") - .append(credits).append(";-1;0;") - .append(creditsSpent).append(";0;") - .append(gamesPlayed).append(';') - .append(secondsPlayed).append(";0;") - .append(inventory) - .toString() - return Future.allOf(classesFuture, charactersFuture) - .thenApply { - faceCodes?.apply { out["FaceCodes"] = this } - newItem?.apply { out["NewItem"] = this } - out["csreward"] = csReward.toString() - - completion?.apply { out["Completion"] = this } - progress?.apply { out["Progress"] = this } - cscompletion?.apply { out["cscompletion"] = this } - cstimestamps1?.apply { out["cstimestamps"] = this } - cstimestamps2?.apply { out["cstimestamps2"] = this } - cstimestamps3?.apply { out["cstimestamps3"] = this } - out["Base"] = settingsBase - out - } + val loader = SettingsMapLoader(this) + return loader.load() } fun setPlayerDataBulk(map: Map<String, String>) { diff --git a/src/main/kotlin/com/jacobtread/relay/database/tables/PlayersTable.kt b/src/main/kotlin/com/jacobtread/relay/database/tables/PlayersTable.kt index d6a9c76..c7ba3e6 100644 --- a/src/main/kotlin/com/jacobtread/relay/database/tables/PlayersTable.kt +++ b/src/main/kotlin/com/jacobtread/relay/database/tables/PlayersTable.kt @@ -5,6 +5,7 @@ import com.jacobtread.relay.database.Database import com.jacobtread.relay.database.Table import com.jacobtread.relay.database.asList import com.jacobtread.relay.database.models.Player +import com.jacobtread.relay.utils.logging.Logger import org.intellij.lang.annotations.Language import java.sql.ResultSet import java.util.concurrent.CompletableFuture as Future @@ -301,12 +302,15 @@ object PlayersTable : Table { setString(4, "") // Inventory setBoolean(5, origin) } - .thenCompose { keys -> + .thenApply { + if (!it.next()) null + else it.getInt(1) + } + .thenCompose { id -> val future = Future<Player>() - if (!keys.next()) { + if (id == null) { future.completeExceptionally(null) } else { - val id = keys.getInt(1) future.complete(Player(id, email, displayName, hashedPassword)) } future @@ -329,14 +333,15 @@ object PlayersTable : Table { setString(1, details.email) setBoolean(2, true) } - .thenCompose { - val player = it.asPlayer() + .thenApply { it.asPlayer() } + .thenCompose { player -> if (player == null) { createOrigin(details) } else { Future.completedFuture(player) } } + } /** @@ -359,6 +364,7 @@ object PlayersTable : Table { ).thenApplyAsync { player -> val dataMap = details.dataMap if (dataMap.isNotEmpty()) { + Logger.logIfDebug { "Storing player origin details" } player.setPlayerDataBulk(dataMap) } player From 6f601a5aabcac613c4a8438027bae1b12fb34f42 Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Sat, 27 Aug 2022 15:04:30 +1200 Subject: [PATCH 6/8] Removed sync server --- src/main/kotlin/com/jacobtread/relay/App.kt | 2 - .../relay/servers/PlayerSyncService.kt | 133 ------------------ 2 files changed, 135 deletions(-) delete mode 100644 src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt diff --git a/src/main/kotlin/com/jacobtread/relay/App.kt b/src/main/kotlin/com/jacobtread/relay/App.kt index 60fd393..dc7df58 100644 --- a/src/main/kotlin/com/jacobtread/relay/App.kt +++ b/src/main/kotlin/com/jacobtread/relay/App.kt @@ -9,7 +9,6 @@ import com.jacobtread.relay.servers.startRedirector import com.jacobtread.relay.servers.startTelemetryServer import com.jacobtread.relay.utils.logging.Logger import io.netty.channel.nio.NioEventLoopGroup -import startSyncServer import java.util.concurrent.CompletableFuture as Future fun main() { @@ -22,7 +21,6 @@ fun main() { startRedirector(bossGroup, workerGroup), startHttpServer(bossGroup, workerGroup), startMainServer(bossGroup, workerGroup), - startSyncServer(bossGroup, workerGroup), startTelemetryServer(bossGroup, workerGroup), startQOSServer(bossGroup, workerGroup) ).get() diff --git a/src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt b/src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt deleted file mode 100644 index 684f474..0000000 --- a/src/main/kotlin/com/jacobtread/relay/servers/PlayerSyncService.kt +++ /dev/null @@ -1,133 +0,0 @@ -package com.jacobtread.relay.servers - -import com.jacobtread.blaze.logging.PacketLogger -import com.jacobtread.relay.Environment -import com.jacobtread.relay.utils.logging.Logger -import io.netty.bootstrap.Bootstrap -import io.netty.bootstrap.ServerBootstrap -import io.netty.buffer.ByteBuf -import io.netty.channel.Channel -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelInboundHandlerAdapter -import io.netty.channel.ChannelInitializer -import io.netty.channel.nio.NioEventLoopGroup -import io.netty.channel.socket.nio.NioServerSocketChannel -import io.netty.channel.socket.nio.NioSocketChannel -import java.io.IOException -import java.util.concurrent.CompletableFuture - -/** - * startRedirector - * - * @param bossGroup The netty boss event loop group - * @param workerGroup The netty worker event loop group - */ -fun startTelemetryServer(bossGroup: NioEventLoopGroup, workerGroup: NioEventLoopGroup): CompletableFuture<Void> { - val startupFuture = CompletableFuture<Void>() - try { - val listenPort = 9988 - ServerBootstrap() - .group(bossGroup, workerGroup) - .channel(NioServerSocketChannel::class.java) - .childHandler(object : ChannelInitializer<Channel>() { - override fun initChannel(ch: Channel) { - val remoteAddress = ch.remoteAddress() - Logger.debug("Connection at $remoteAddress to telemetry Server") - PacketLogger.setEnabled(ch, true) - ch.pipeline().addLast(TelemetryHandler(ch)) - } - }) - .bind(listenPort) - .addListener { - Logger.info("Started Telemetry on port 9988") - startupFuture.complete(null) - } - } catch (e: IOException) { - val reason = e.message ?: e.javaClass.simpleName - Logger.fatal("Unable to start telemetry server: $reason") - } - return startupFuture -} - -class TelemetryHandler(val clientChannel: Channel) : ChannelInboundHandlerAdapter() { - - private var sessionId: Int = -1 - private fun createServerChannel(): Channel { - val channelFuture = Bootstrap() - .group(NioEventLoopGroup()) - .channel(NioSocketChannel::class.java) - .handler(OfficialHandler()) - .connect("159.153.235.32", 9988) - .sync() - return channelFuture.channel() - } - private var serverChannel: Channel = createServerChannel() - - inner class OfficialHandler : ChannelInboundHandlerAdapter() { - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - if (msg is ByteBuf) { - Logger.info("[TELEMETRY] [SERVER] Sent bytes ${msg.readableBytes()}") - } - clientChannel.writeAndFlush(msg) - } - } - - private fun decodeTLM3(value: String): String { - - val telemtryKey = "The truth is back in style." - val keyChars = telemtryKey.toCharArray() - val startIndex = value.indexOf('-') - val out = StringBuilder() - if (startIndex != -1) { - val start = startIndex + 1 - val chars = value.toCharArray() - for (i in start until value.length) { - val charAt = chars[i] - val newChar = keyChars[(i - start) % telemtryKey.length] - val xorValue = charAt.code xor newChar.code - if (xorValue <= 128) { - out.append(xorValue.toChar()) - } else { - out.append((newChar.code xor (charAt.code - 128)).toChar()) - } - } - } - return out.toString() - } - - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - if (msg is ByteBuf) { - Logger.info("[TELEMETRY] [CLIENT] Sent bytes ${msg.readableBytes()}") - - msg.skipBytes(10) // Skip Heading - val text = msg.readCharSequence(msg.readableBytes(), Charsets.UTF_8) - val lines = text.split('\n') - val dataMap = HashMap<String, String>() - lines.forEach { line -> - val parts = line.split('=', limit = 2) - if (parts.size == 2) { - dataMap[parts[0]] = parts[1] - } - } - - val auth = dataMap["AUTH"] - if (auth != null) { - sessionId = auth.toInt() - } - val tlm3 = dataMap["TLM3"] - if (tlm3 != null) { - val decoded = decodeTLM3(tlm3).replace('/', '\n') - Logger.info("Telemetry TLM3: $decoded") - } - - - Logger.info(dataMap.toString()) - Logger.debug("TELEMETRY DATA: $text") - } - if (serverChannel.isOpen) { - serverChannel.writeAndFlush(msg) - } else { - serverChannel = createServerChannel() - } - } -} \ No newline at end of file From e18163baad5f083c22d151edd8dd0ac0276f95a1 Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Sat, 27 Aug 2022 15:05:32 +1200 Subject: [PATCH 7/8] Removed temp servers for bug fix release --- src/main/kotlin/com/jacobtread/relay/App.kt | 4 - .../com/jacobtread/relay/servers/QOSServer.kt | 84 ----------- .../relay/servers/TelemetryServer.kt | 133 ------------------ 3 files changed, 221 deletions(-) delete mode 100644 src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt delete mode 100644 src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt diff --git a/src/main/kotlin/com/jacobtread/relay/App.kt b/src/main/kotlin/com/jacobtread/relay/App.kt index dc7df58..3ce94a1 100644 --- a/src/main/kotlin/com/jacobtread/relay/App.kt +++ b/src/main/kotlin/com/jacobtread/relay/App.kt @@ -4,9 +4,7 @@ package com.jacobtread.relay import com.jacobtread.relay.http.startHttpServer import com.jacobtread.relay.servers.startMainServer -import com.jacobtread.relay.servers.startQOSServer import com.jacobtread.relay.servers.startRedirector -import com.jacobtread.relay.servers.startTelemetryServer import com.jacobtread.relay.utils.logging.Logger import io.netty.channel.nio.NioEventLoopGroup import java.util.concurrent.CompletableFuture as Future @@ -21,8 +19,6 @@ fun main() { startRedirector(bossGroup, workerGroup), startHttpServer(bossGroup, workerGroup), startMainServer(bossGroup, workerGroup), - startTelemetryServer(bossGroup, workerGroup), - startQOSServer(bossGroup, workerGroup) ).get() System.gc() // Cleanup after initialization diff --git a/src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt b/src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt deleted file mode 100644 index 92767a9..0000000 --- a/src/main/kotlin/com/jacobtread/relay/servers/QOSServer.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.jacobtread.relay.servers - -import com.jacobtread.blaze.logging.PacketLogger -import com.jacobtread.relay.Environment -import com.jacobtread.relay.utils.logging.Logger -import io.netty.bootstrap.Bootstrap -import io.netty.bootstrap.ServerBootstrap -import io.netty.buffer.ByteBuf -import io.netty.channel.Channel -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelInboundHandlerAdapter -import io.netty.channel.ChannelInitializer -import io.netty.channel.nio.NioEventLoopGroup -import io.netty.channel.socket.nio.NioServerSocketChannel -import io.netty.channel.socket.nio.NioSocketChannel -import java.io.IOException -import java.util.concurrent.CompletableFuture - -/** - * startRedirector - * - * @param bossGroup The netty boss event loop group - * @param workerGroup The netty worker event loop group - */ -fun startQOSServer(bossGroup: NioEventLoopGroup, workerGroup: NioEventLoopGroup): CompletableFuture<Void> { - val startupFuture = CompletableFuture<Void>() - try { - val listenPort = 17499 - ServerBootstrap() - .group(bossGroup, workerGroup) - .channel(NioServerSocketChannel::class.java) - .childHandler(object : ChannelInitializer<Channel>() { - override fun initChannel(ch: Channel) { - val remoteAddress = ch.remoteAddress() - Logger.debug("Connection at $remoteAddress to QOS Server") - PacketLogger.setEnabled(ch, true) - ch.pipeline().addLast(QOSHandler(ch)) - } - }) - .bind(listenPort) - .addListener { - Logger.info("Started QOS on port 17499") - startupFuture.complete(null) - } - } catch (e: IOException) { - val reason = e.message ?: e.javaClass.simpleName - Logger.fatal("Unable to start telemetry server: $reason") - } - return startupFuture -} - -class QOSHandler(val clientChannel: Channel) : ChannelInboundHandlerAdapter() { - - private fun createServerChannel(): Channel { - val channelFuture = Bootstrap() - .group(NioEventLoopGroup()) - .channel(NioSocketChannel::class.java) - .handler(OfficialHandler()) - .connect("162.244.53.174", 17499) - .sync() - return channelFuture.channel() - } - private var serverChannel: Channel = createServerChannel() - - inner class OfficialHandler : ChannelInboundHandlerAdapter() { - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - if (msg is ByteBuf) { - Logger.info("[QOSSERVER] [SERVER] Sent bytes ${msg.readableBytes()}") - } - clientChannel.writeAndFlush(msg) - } - } - - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - if (msg is ByteBuf) { - Logger.info("[QOSSERVER] [CLIENT] Sent bytes ${msg.readableBytes()}") - } - if (serverChannel.isOpen) { - serverChannel.writeAndFlush(msg) - } else { - serverChannel = createServerChannel() - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt b/src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt deleted file mode 100644 index 684f474..0000000 --- a/src/main/kotlin/com/jacobtread/relay/servers/TelemetryServer.kt +++ /dev/null @@ -1,133 +0,0 @@ -package com.jacobtread.relay.servers - -import com.jacobtread.blaze.logging.PacketLogger -import com.jacobtread.relay.Environment -import com.jacobtread.relay.utils.logging.Logger -import io.netty.bootstrap.Bootstrap -import io.netty.bootstrap.ServerBootstrap -import io.netty.buffer.ByteBuf -import io.netty.channel.Channel -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelInboundHandlerAdapter -import io.netty.channel.ChannelInitializer -import io.netty.channel.nio.NioEventLoopGroup -import io.netty.channel.socket.nio.NioServerSocketChannel -import io.netty.channel.socket.nio.NioSocketChannel -import java.io.IOException -import java.util.concurrent.CompletableFuture - -/** - * startRedirector - * - * @param bossGroup The netty boss event loop group - * @param workerGroup The netty worker event loop group - */ -fun startTelemetryServer(bossGroup: NioEventLoopGroup, workerGroup: NioEventLoopGroup): CompletableFuture<Void> { - val startupFuture = CompletableFuture<Void>() - try { - val listenPort = 9988 - ServerBootstrap() - .group(bossGroup, workerGroup) - .channel(NioServerSocketChannel::class.java) - .childHandler(object : ChannelInitializer<Channel>() { - override fun initChannel(ch: Channel) { - val remoteAddress = ch.remoteAddress() - Logger.debug("Connection at $remoteAddress to telemetry Server") - PacketLogger.setEnabled(ch, true) - ch.pipeline().addLast(TelemetryHandler(ch)) - } - }) - .bind(listenPort) - .addListener { - Logger.info("Started Telemetry on port 9988") - startupFuture.complete(null) - } - } catch (e: IOException) { - val reason = e.message ?: e.javaClass.simpleName - Logger.fatal("Unable to start telemetry server: $reason") - } - return startupFuture -} - -class TelemetryHandler(val clientChannel: Channel) : ChannelInboundHandlerAdapter() { - - private var sessionId: Int = -1 - private fun createServerChannel(): Channel { - val channelFuture = Bootstrap() - .group(NioEventLoopGroup()) - .channel(NioSocketChannel::class.java) - .handler(OfficialHandler()) - .connect("159.153.235.32", 9988) - .sync() - return channelFuture.channel() - } - private var serverChannel: Channel = createServerChannel() - - inner class OfficialHandler : ChannelInboundHandlerAdapter() { - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - if (msg is ByteBuf) { - Logger.info("[TELEMETRY] [SERVER] Sent bytes ${msg.readableBytes()}") - } - clientChannel.writeAndFlush(msg) - } - } - - private fun decodeTLM3(value: String): String { - - val telemtryKey = "The truth is back in style." - val keyChars = telemtryKey.toCharArray() - val startIndex = value.indexOf('-') - val out = StringBuilder() - if (startIndex != -1) { - val start = startIndex + 1 - val chars = value.toCharArray() - for (i in start until value.length) { - val charAt = chars[i] - val newChar = keyChars[(i - start) % telemtryKey.length] - val xorValue = charAt.code xor newChar.code - if (xorValue <= 128) { - out.append(xorValue.toChar()) - } else { - out.append((newChar.code xor (charAt.code - 128)).toChar()) - } - } - } - return out.toString() - } - - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - if (msg is ByteBuf) { - Logger.info("[TELEMETRY] [CLIENT] Sent bytes ${msg.readableBytes()}") - - msg.skipBytes(10) // Skip Heading - val text = msg.readCharSequence(msg.readableBytes(), Charsets.UTF_8) - val lines = text.split('\n') - val dataMap = HashMap<String, String>() - lines.forEach { line -> - val parts = line.split('=', limit = 2) - if (parts.size == 2) { - dataMap[parts[0]] = parts[1] - } - } - - val auth = dataMap["AUTH"] - if (auth != null) { - sessionId = auth.toInt() - } - val tlm3 = dataMap["TLM3"] - if (tlm3 != null) { - val decoded = decodeTLM3(tlm3).replace('/', '\n') - Logger.info("Telemetry TLM3: $decoded") - } - - - Logger.info(dataMap.toString()) - Logger.debug("TELEMETRY DATA: $text") - } - if (serverChannel.isOpen) { - serverChannel.writeAndFlush(msg) - } else { - serverChannel = createServerChannel() - } - } -} \ No newline at end of file From a70f6739b288b7ebe95489dec2d92c171138b5bc Mon Sep 17 00:00:00 2001 From: Jacobtread <jacobtread@gmail.com> Date: Sat, 27 Aug 2022 15:06:52 +1200 Subject: [PATCH 8/8] Rem for debug merge --- .../relay/sessions/handlers/UtilHandlers.kt | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt b/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt index 1d12fc5..78eae2d 100644 --- a/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt +++ b/src/main/kotlin/com/jacobtread/relay/sessions/handlers/UtilHandlers.kt @@ -12,24 +12,6 @@ import com.jacobtread.relay.sessions.Session import com.jacobtread.relay.utils.logging.Logger import com.jacobtread.relay.utils.unixTimeSeconds -@PacketHandler(Components.UTIL, Commands.GET_TELEMETRY_SERVER) -fun Session.handleGetTelemetryServer(packet:Packet) { - push(packet.respond { - text("ADRS", Environment.externalAddress) - number("ANON", 0) - text("DISA", "AD,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AW,AX,AZ,BA,BB,BD,BF,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CC,CD,CF,CG,CI,CK,CL,CM,CN,CO,CR,CU,CV,CX,DJ,DM,DO,DZ,EC,EG,EH,ER,ET,FJ,FK,FM,FO,GA,GD,GE,GF,GG,GH,GI,GL,GM,GN,GP,GQ,GS,GT,GU,GW,GY,HM,HN,HT,ID,IL,IM,IN,IO,IQ,IR,IS,JE,JM,JO,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,LY,MA,MC,MD,ME,MG,MH,ML,MM,MN,MO,MP,MQ,MR,MS,MU,MV,MW,MY,MZ,NA,NC,NE,NF,NG,NI,NP,NR,NU,OM,PA,PE,PF,PG,PH,PK,PM,PN,PS,PW,PY,QA,RE,RS,RW,SA,SB,SC,SD,SG,SH,SJ,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TL,TM,TN,TO,TT,TV,TZ,UA,UG,UM,UY,UZ,VA,VC,VE,VG,VN,VU,WF,WS,YE,YT,ZM,ZW,ZZ") - text("FILT", "-UION/****") - number("LOC", 0x656e5553) - text("NOOK", "US,CA,MX") - number("PORT", 9988) - number("SDLY", 15000) - text("SESS", "Evi8itOCVpD") - text("SKEY", sessionId.toString()) - number("SPCT", 75) - text("STIM") - }) -} - /** * Handles the pre authentication packet this includes information about the * client such as location, version, platform, etc. This response with information