diff --git a/src/Test.kt b/src/Test.kt index 5d592e9..241f115 100644 --- a/src/Test.kt +++ b/src/Test.kt @@ -1,12 +1,31 @@ -import dev.w1zzrd.bungee.BungeeServer +import dev.w1zzrd.bungee.BungeeRTCPRouter +import dev.w1zzrd.bungee.BungeeRTCPServer +import java.io.File import java.net.InetAddress +import java.nio.file.Files +import java.nio.file.Path +import java.security.KeyFactory +import java.security.spec.PKCS8EncodedKeySpec +import java.security.spec.X509EncodedKeySpec fun main(args: Array){ - // Route localhost:80 -> google.com - val server = BungeeServer( - InetAddress.getByName("0.0.0.0"), 25565, - InetAddress.getByName("192.168.1.145"), 25565 - ) - server.start() - server.waitFor() + val privKey = KeyFactory.getInstance("RSA") + .generatePrivate(PKCS8EncodedKeySpec(Files.readAllBytes(Path.of("./private_key.der")))) + + val pubKey = KeyFactory.getInstance("RSA") + .generatePublic(X509EncodedKeySpec(Files.readAllBytes(Path.of("./public_key.der")))) + + Thread(Runnable { + BungeeRTCPRouter(InetAddress.getByName("0.0.0.0"), 6969, pubKey).listen() + }).start() + + Thread.sleep(20) + + BungeeRTCPServer( + InetAddress.getByName("0.0.0.0"), + 6969, + InetAddress.getByName("192.168.1.145"), + 25565, + privKey + ).start() } \ No newline at end of file diff --git a/src/dev/w1zzrd/bungee/BungeeRTCPRouter.kt b/src/dev/w1zzrd/bungee/BungeeRTCPRouter.kt index b868cb6..60261b9 100644 --- a/src/dev/w1zzrd/bungee/BungeeRTCPRouter.kt +++ b/src/dev/w1zzrd/bungee/BungeeRTCPRouter.kt @@ -20,7 +20,7 @@ class BungeeRTCPRouter( private lateinit var routeSocket: Socket private var alive = false private var canStart = true - private val headerBuffer = ByteBuffer.allocateDirect(13) // [ID (byte)][(CUID) long][DLEN (int)] + private val headerBuffer = ByteBuffer.wrap(ByteArray(13)) // [ID (byte)][(CUID) long][DLEN (int)] fun listen(){ if(!canStart) throw IllegalStateException("Already started/stopped") @@ -35,7 +35,9 @@ class BungeeRTCPRouter( val checkBytes = ByteArray(256) val rand = ThreadLocalRandom.current() val fromClients = ByteArray(BUFFER_SIZE) + val wrappedClientBuffer = ByteBuffer.wrap(fromClients) val fromRoute = ByteArray(BUFFER_SIZE) + val wrappedRouteBuffer = ByteBuffer.wrap(fromRoute) var routeBytes = 0 @@ -80,9 +82,9 @@ class BungeeRTCPRouter( } // We have a client. Let's check if they can authenticate - if(readBytes >= 4 && fromClients.intify(0) == 0x13376969){ // Tell router that you would like to authenticate + if(readBytes >= 4 && wrappedClientBuffer.getInt(0) == 0x13376969){ // Tell router that you would like to authenticate if(readBytes >= (4 + 4)){ - val signedDataLength = fromClients.intify(4) + val signedDataLength = wrappedClientBuffer.getInt(4) if(readBytes >= (4 + 4 + signedDataLength)){ // We have the signed data; let's verify its integrity @@ -92,6 +94,7 @@ class BungeeRTCPRouter( if(sig.verify(fromClients, 4 + 4, signedDataLength)){ // We have a verified remote route! :D routeSocket = tryRoute!! + println("RTCP server verified!") break }else{ // Verification failed :( @@ -130,7 +133,7 @@ class BungeeRTCPRouter( try { val stream = client.getInputStream() if (stream.available() > 0) { - val read = stream.read(fromClients) + val read = stream.read(fromClients, 0, fromClients.size) if (read > 0 && !sendClientMessageToServer(uid, fromClients, 0, read)) { System.err.println("Unexpected endpoint disconnection") @@ -163,21 +166,24 @@ class BungeeRTCPRouter( // Parse data packet if((routeBytes + read) - parsed < 13) break@parseLoop // Not enough data - val uid = fromRoute.longify(parsed + 1) - val dLen = fromRoute.intify(parsed + 1 + 8) + val uid = wrappedRouteBuffer.getLong(parsed +1) + val dLen = wrappedRouteBuffer.getInt(parsed + 1 + 8) if((routeBytes + read) - parsed < 13 + dLen) break@parseLoop // All the data hasn't arrived - clients.keys.firstOrNull { clients[it] == uid } - ?.getOutputStream() - ?.write(fromRoute, parsed + 13, dLen) - + try { + clients.keys.firstOrNull { clients[it] == uid } + ?.getOutputStream() + ?.write(fromRoute, parsed + 13, dLen) + }catch(e: Throwable){ + notifyClientDisconnect(uid) + } parsed += 13 + dLen } 1.toByte() -> { // Handle disconnection - val uid = fromRoute.longify(parsed + 1) + val uid = wrappedRouteBuffer.getLong(parsed + 1) if(clients.values.contains(uid)){ val toDrop = clients.keys.firstOrNull { clients[it] == uid } if(toDrop != null) { @@ -229,31 +235,4 @@ class BungeeRTCPRouter( }catch(e: Throwable){ false } -} - - -fun ByteArray.intify(offset: Int) - = this[offset].toInt().and(0xFF).or( - this[offset + 1].toInt().and(0xFF).shl(8) -).or( - this[offset + 2].toInt().and(0xFF).shl(16) -).or( - this[offset + 3].toInt().and(0xFF).shl(24) -) - -fun ByteArray.longify(offset: Int) - = this[offset].toLong().and(0xFF).or( - this[offset + 1].toLong().and(0xFF).shl(8) -).or( - this[offset + 2].toLong().and(0xFF).shl(16) -).or( - this[offset + 3].toLong().and(0xFF).shl(24) -).or( - this[offset + 4].toLong().and(0xFF).shl(32) -).or( - this[offset + 5].toLong().and(0xFF).shl(40) -).or( - this[offset + 6].toLong().and(0xFF).shl(48) -).or( - this[offset + 7].toLong().and(0xFF).shl(56) -) \ No newline at end of file +} \ No newline at end of file diff --git a/src/dev/w1zzrd/bungee/BungeeRTCPServer.kt b/src/dev/w1zzrd/bungee/BungeeRTCPServer.kt index d447a11..7afe223 100644 --- a/src/dev/w1zzrd/bungee/BungeeRTCPServer.kt +++ b/src/dev/w1zzrd/bungee/BungeeRTCPServer.kt @@ -22,9 +22,10 @@ class BungeeRTCPServer( private var canStart = true private val serverSocket = Socket() private val buffer = ByteArray(BUFFER_SIZE) + private val wrappedServerBuffer = ByteBuffer.wrap(buffer) private val clientBuffer = ByteArray(BUFFER_SIZE) private var alive = false - private val headerBuffer = ByteBuffer.allocateDirect(13) + private val headerBuffer = ByteBuffer.wrap(ByteArray(13)) fun start(){ if(!canStart) throw IllegalStateException("Already started/stopped") @@ -42,14 +43,8 @@ class BungeeRTCPServer( sig.initSign(privateKey) sig.update(buffer, 0, 256) val signLen = sig.sign(buffer, 8, buffer.size - 8) - buffer[0] = 0x69.toByte() - buffer[1] = 0x69.toByte() - buffer[2] = 0x37.toByte() - buffer[3] = 0x13.toByte() - buffer[4] = signLen.and(0xFF).toByte() - buffer[5] = signLen.ushr(8).and(0xFF).toByte() - buffer[6] = signLen.ushr(16).and(0xFF).toByte() - buffer[7] = signLen.ushr(24).and(0xFF).toByte() + wrappedServerBuffer.putInt(0, 0x13376969) + wrappedServerBuffer.putInt(4, signLen) // Send signature write.write(buffer, 0, 8 + signLen) @@ -62,7 +57,7 @@ class BungeeRTCPServer( var parsed = 0 parseLoop@while(bufferBytes - parsed > 9){ - val uid = buffer.longify(parsed + 1) + val uid = wrappedServerBuffer.getLong(parsed + 1) when(buffer[parsed]){ 0.toByte() -> { @@ -73,7 +68,7 @@ class BungeeRTCPServer( 1.toByte() -> { // Data from client if(bufferBytes - parsed > 13){ - val dLen = buffer.intify(parsed + 9) + val dLen = wrappedServerBuffer.getInt(parsed + 9) if(bufferBytes < parsed + dLen) break@parseLoop // Not enough data try { // Send data to server @@ -104,7 +99,7 @@ class BungeeRTCPServer( for((uid, client) in vClients){ try { val stream = client.getInputStream() - if (read.available() > 0) { + if (stream.available() > 0) { val clientRead = stream.read(clientBuffer, 0, clientBuffer.size) if (clientRead > 0) sendVClientPacket(uid, clientBuffer, 0, clientRead) } @@ -116,7 +111,7 @@ class BungeeRTCPServer( } fun sendVClientPacket(uid: Long, data: ByteArray, off: Int, len: Int){ - notifyClientAction(uid, 0, data.size) + notifyClientAction(uid, 0, len) sendMessageToRouter(data, off, len) } fun notifyClientDrop(uid: Long) = notifyClientAction(uid, 1)