Fix various bugs

This commit is contained in:
Gabriel Tofvesson 2019-04-16 16:24:53 +02:00
parent 182f909cce
commit ba427e0a6f
3 changed files with 53 additions and 60 deletions

View File

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

View File

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

View File

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