Fix various bugs
This commit is contained in:
parent
182f909cce
commit
ba427e0a6f
src
35
src/Test.kt
35
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.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>){
|
fun main(args: Array<String>){
|
||||||
// Route localhost:80 -> google.com
|
val privKey = KeyFactory.getInstance("RSA")
|
||||||
val server = BungeeServer(
|
.generatePrivate(PKCS8EncodedKeySpec(Files.readAllBytes(Path.of("./private_key.der"))))
|
||||||
InetAddress.getByName("0.0.0.0"), 25565,
|
|
||||||
InetAddress.getByName("192.168.1.145"), 25565
|
val pubKey = KeyFactory.getInstance("RSA")
|
||||||
)
|
.generatePublic(X509EncodedKeySpec(Files.readAllBytes(Path.of("./public_key.der"))))
|
||||||
server.start()
|
|
||||||
server.waitFor()
|
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()
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ class BungeeRTCPRouter(
|
|||||||
private lateinit var routeSocket: Socket
|
private lateinit var routeSocket: Socket
|
||||||
private var alive = false
|
private var alive = false
|
||||||
private var canStart = true
|
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(){
|
fun listen(){
|
||||||
if(!canStart) throw IllegalStateException("Already started/stopped")
|
if(!canStart) throw IllegalStateException("Already started/stopped")
|
||||||
@ -35,7 +35,9 @@ class BungeeRTCPRouter(
|
|||||||
val checkBytes = ByteArray(256)
|
val checkBytes = ByteArray(256)
|
||||||
val rand = ThreadLocalRandom.current()
|
val rand = ThreadLocalRandom.current()
|
||||||
val fromClients = ByteArray(BUFFER_SIZE)
|
val fromClients = ByteArray(BUFFER_SIZE)
|
||||||
|
val wrappedClientBuffer = ByteBuffer.wrap(fromClients)
|
||||||
val fromRoute = ByteArray(BUFFER_SIZE)
|
val fromRoute = ByteArray(BUFFER_SIZE)
|
||||||
|
val wrappedRouteBuffer = ByteBuffer.wrap(fromRoute)
|
||||||
var routeBytes = 0
|
var routeBytes = 0
|
||||||
|
|
||||||
|
|
||||||
@ -80,9 +82,9 @@ class BungeeRTCPRouter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We have a client. Let's check if they can authenticate
|
// 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)){
|
if(readBytes >= (4 + 4)){
|
||||||
val signedDataLength = fromClients.intify(4)
|
val signedDataLength = wrappedClientBuffer.getInt(4)
|
||||||
|
|
||||||
if(readBytes >= (4 + 4 + signedDataLength)){
|
if(readBytes >= (4 + 4 + signedDataLength)){
|
||||||
// We have the signed data; let's verify its integrity
|
// We have the signed data; let's verify its integrity
|
||||||
@ -92,6 +94,7 @@ class BungeeRTCPRouter(
|
|||||||
if(sig.verify(fromClients, 4 + 4, signedDataLength)){
|
if(sig.verify(fromClients, 4 + 4, signedDataLength)){
|
||||||
// We have a verified remote route! :D
|
// We have a verified remote route! :D
|
||||||
routeSocket = tryRoute!!
|
routeSocket = tryRoute!!
|
||||||
|
println("RTCP server verified!")
|
||||||
break
|
break
|
||||||
}else{
|
}else{
|
||||||
// Verification failed :(
|
// Verification failed :(
|
||||||
@ -130,7 +133,7 @@ class BungeeRTCPRouter(
|
|||||||
try {
|
try {
|
||||||
val stream = client.getInputStream()
|
val stream = client.getInputStream()
|
||||||
if (stream.available() > 0) {
|
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)) {
|
if (read > 0 && !sendClientMessageToServer(uid, fromClients, 0, read)) {
|
||||||
System.err.println("Unexpected endpoint disconnection")
|
System.err.println("Unexpected endpoint disconnection")
|
||||||
@ -163,21 +166,24 @@ class BungeeRTCPRouter(
|
|||||||
// Parse data packet
|
// Parse data packet
|
||||||
if((routeBytes + read) - parsed < 13) break@parseLoop // Not enough data
|
if((routeBytes + read) - parsed < 13) break@parseLoop // Not enough data
|
||||||
|
|
||||||
val uid = fromRoute.longify(parsed + 1)
|
val uid = wrappedRouteBuffer.getLong(parsed +1)
|
||||||
val dLen = fromRoute.intify(parsed + 1 + 8)
|
val dLen = wrappedRouteBuffer.getInt(parsed + 1 + 8)
|
||||||
|
|
||||||
if((routeBytes + read) - parsed < 13 + dLen) break@parseLoop // All the data hasn't arrived
|
if((routeBytes + read) - parsed < 13 + dLen) break@parseLoop // All the data hasn't arrived
|
||||||
|
|
||||||
|
try {
|
||||||
clients.keys.firstOrNull { clients[it] == uid }
|
clients.keys.firstOrNull { clients[it] == uid }
|
||||||
?.getOutputStream()
|
?.getOutputStream()
|
||||||
?.write(fromRoute, parsed + 13, dLen)
|
?.write(fromRoute, parsed + 13, dLen)
|
||||||
|
}catch(e: Throwable){
|
||||||
|
notifyClientDisconnect(uid)
|
||||||
|
}
|
||||||
parsed += 13 + dLen
|
parsed += 13 + dLen
|
||||||
}
|
}
|
||||||
|
|
||||||
1.toByte() -> {
|
1.toByte() -> {
|
||||||
// Handle disconnection
|
// Handle disconnection
|
||||||
val uid = fromRoute.longify(parsed + 1)
|
val uid = wrappedRouteBuffer.getLong(parsed + 1)
|
||||||
if(clients.values.contains(uid)){
|
if(clients.values.contains(uid)){
|
||||||
val toDrop = clients.keys.firstOrNull { clients[it] == uid }
|
val toDrop = clients.keys.firstOrNull { clients[it] == uid }
|
||||||
if(toDrop != null) {
|
if(toDrop != null) {
|
||||||
@ -230,30 +236,3 @@ class BungeeRTCPRouter(
|
|||||||
false
|
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)
|
|
||||||
)
|
|
@ -22,9 +22,10 @@ class BungeeRTCPServer(
|
|||||||
private var canStart = true
|
private var canStart = true
|
||||||
private val serverSocket = Socket()
|
private val serverSocket = Socket()
|
||||||
private val buffer = ByteArray(BUFFER_SIZE)
|
private val buffer = ByteArray(BUFFER_SIZE)
|
||||||
|
private val wrappedServerBuffer = ByteBuffer.wrap(buffer)
|
||||||
private val clientBuffer = ByteArray(BUFFER_SIZE)
|
private val clientBuffer = ByteArray(BUFFER_SIZE)
|
||||||
private var alive = false
|
private var alive = false
|
||||||
private val headerBuffer = ByteBuffer.allocateDirect(13)
|
private val headerBuffer = ByteBuffer.wrap(ByteArray(13))
|
||||||
|
|
||||||
fun start(){
|
fun start(){
|
||||||
if(!canStart) throw IllegalStateException("Already started/stopped")
|
if(!canStart) throw IllegalStateException("Already started/stopped")
|
||||||
@ -42,14 +43,8 @@ class BungeeRTCPServer(
|
|||||||
sig.initSign(privateKey)
|
sig.initSign(privateKey)
|
||||||
sig.update(buffer, 0, 256)
|
sig.update(buffer, 0, 256)
|
||||||
val signLen = sig.sign(buffer, 8, buffer.size - 8)
|
val signLen = sig.sign(buffer, 8, buffer.size - 8)
|
||||||
buffer[0] = 0x69.toByte()
|
wrappedServerBuffer.putInt(0, 0x13376969)
|
||||||
buffer[1] = 0x69.toByte()
|
wrappedServerBuffer.putInt(4, signLen)
|
||||||
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()
|
|
||||||
|
|
||||||
// Send signature
|
// Send signature
|
||||||
write.write(buffer, 0, 8 + signLen)
|
write.write(buffer, 0, 8 + signLen)
|
||||||
@ -62,7 +57,7 @@ class BungeeRTCPServer(
|
|||||||
|
|
||||||
var parsed = 0
|
var parsed = 0
|
||||||
parseLoop@while(bufferBytes - parsed > 9){
|
parseLoop@while(bufferBytes - parsed > 9){
|
||||||
val uid = buffer.longify(parsed + 1)
|
val uid = wrappedServerBuffer.getLong(parsed + 1)
|
||||||
|
|
||||||
when(buffer[parsed]){
|
when(buffer[parsed]){
|
||||||
0.toByte() -> {
|
0.toByte() -> {
|
||||||
@ -73,7 +68,7 @@ class BungeeRTCPServer(
|
|||||||
1.toByte() -> {
|
1.toByte() -> {
|
||||||
// Data from client
|
// Data from client
|
||||||
if(bufferBytes - parsed > 13){
|
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
|
if(bufferBytes < parsed + dLen) break@parseLoop // Not enough data
|
||||||
try {
|
try {
|
||||||
// Send data to server
|
// Send data to server
|
||||||
@ -104,7 +99,7 @@ class BungeeRTCPServer(
|
|||||||
for((uid, client) in vClients){
|
for((uid, client) in vClients){
|
||||||
try {
|
try {
|
||||||
val stream = client.getInputStream()
|
val stream = client.getInputStream()
|
||||||
if (read.available() > 0) {
|
if (stream.available() > 0) {
|
||||||
val clientRead = stream.read(clientBuffer, 0, clientBuffer.size)
|
val clientRead = stream.read(clientBuffer, 0, clientBuffer.size)
|
||||||
if (clientRead > 0) sendVClientPacket(uid, clientBuffer, 0, clientRead)
|
if (clientRead > 0) sendVClientPacket(uid, clientBuffer, 0, clientRead)
|
||||||
}
|
}
|
||||||
@ -116,7 +111,7 @@ class BungeeRTCPServer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun sendVClientPacket(uid: Long, data: ByteArray, off: Int, len: Int){
|
fun sendVClientPacket(uid: Long, data: ByteArray, off: Int, len: Int){
|
||||||
notifyClientAction(uid, 0, data.size)
|
notifyClientAction(uid, 0, len)
|
||||||
sendMessageToRouter(data, off, len)
|
sendMessageToRouter(data, off, len)
|
||||||
}
|
}
|
||||||
fun notifyClientDrop(uid: Long) = notifyClientAction(uid, 1)
|
fun notifyClientDrop(uid: Long) = notifyClientAction(uid, 1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user