Add standard relay server
This commit is contained in:
commit
32314eba68
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
10
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="WeakerAccess" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
|
||||||
|
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" />
|
||||||
|
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
10
.idea/kotlinc.xml
generated
Normal file
10
.idea/kotlinc.xml
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Kotlin2JvmCompilerArguments">
|
||||||
|
<option name="jvmTarget" value="1.8" />
|
||||||
|
</component>
|
||||||
|
<component name="KotlinCommonCompilerArguments">
|
||||||
|
<option name="apiVersion" value="1.2" />
|
||||||
|
<option name="languageVersion" value="1.2" />
|
||||||
|
</component>
|
||||||
|
</project>
|
15
.idea/libraries/KotlinJavaRuntime.xml
generated
Normal file
15
.idea/libraries/KotlinJavaRuntime.xml
generated
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="KotlinJavaRuntime">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar!/" />
|
||||||
|
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
|
||||||
|
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC />
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-sources.jar!/" />
|
||||||
|
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect-sources.jar!/" />
|
||||||
|
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test-sources.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</component>
|
6
.idea/misc.xml
generated
Normal file
6
.idea/misc.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/Bungee.iml" filepath="$PROJECT_DIR$/Bungee.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
12
Bungee.iml
Normal file
12
Bungee.iml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
12
src/Test.kt
Normal file
12
src/Test.kt
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import dev.w1zzrd.bungee.BungeeServer
|
||||||
|
import java.net.InetAddress
|
||||||
|
|
||||||
|
fun main(args: Array<String>){
|
||||||
|
// Route localhost:80 -> google.com
|
||||||
|
val server = BungeeServer(
|
||||||
|
InetAddress.getByName("0.0.0.0"), 25565 .. 25565,
|
||||||
|
InetAddress.getByName("192.168.1.145"), 25565
|
||||||
|
)
|
||||||
|
server.start()
|
||||||
|
server.waitFor()
|
||||||
|
}
|
106
src/dev/w1zzrd/bungee/BungeeServer.kt
Normal file
106
src/dev/w1zzrd/bungee/BungeeServer.kt
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
package dev.w1zzrd.bungee
|
||||||
|
|
||||||
|
import java.net.*
|
||||||
|
|
||||||
|
const val SERVER_CONNECTION_BACKLOG = 65536
|
||||||
|
const val BUFFER_SIZE = 16777216 // 16 MiB communication buffer
|
||||||
|
|
||||||
|
class BungeeServer(
|
||||||
|
private val listenAddr: InetAddress,
|
||||||
|
private val port: Int,
|
||||||
|
private val routeTo: InetAddress,
|
||||||
|
private val routePort: Int
|
||||||
|
){
|
||||||
|
private var canStart = true
|
||||||
|
private val serverSocket = ServerSocket()
|
||||||
|
private val buffer = ByteArray(BUFFER_SIZE)
|
||||||
|
private val listenThread = Thread(this::acceptSocket)
|
||||||
|
private val clients = HashMap<Socket, Socket>()
|
||||||
|
private var alive = false
|
||||||
|
|
||||||
|
init {
|
||||||
|
serverSocket.soTimeout = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start listening for incoming connections.
|
||||||
|
*/
|
||||||
|
fun start(){
|
||||||
|
if(!canStart) throw IllegalStateException("Already started/stopped")
|
||||||
|
canStart = false
|
||||||
|
|
||||||
|
// Set up server socket
|
||||||
|
serverSocket.bind(InetSocketAddress(listenAddr, port), SERVER_CONNECTION_BACKLOG)
|
||||||
|
|
||||||
|
listenThread.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun waitFor() = listenThread.join()
|
||||||
|
|
||||||
|
private fun acceptSocket(){
|
||||||
|
alive = true
|
||||||
|
while(alive) {
|
||||||
|
// Accept new clients
|
||||||
|
serverSocket.acceptPassthrough()
|
||||||
|
|
||||||
|
// Remove connections that have been dropped
|
||||||
|
purgeDeadConnections()
|
||||||
|
|
||||||
|
// Forward data
|
||||||
|
for ((clientSocket, routeSocket) in clients) {
|
||||||
|
// Bidirectional communication
|
||||||
|
clientSocket.forwardConnection(routeSocket)
|
||||||
|
routeSocket.forwardConnection(clientSocket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun purgeDeadConnections(){
|
||||||
|
for((clientSocket, routeSocket) in clients){
|
||||||
|
if(
|
||||||
|
!(clientSocket.isConnected && routeSocket.isConnected) ||
|
||||||
|
clientSocket.isClosed ||
|
||||||
|
routeSocket.isClosed
|
||||||
|
){
|
||||||
|
purgeConnectionRoute(clientSocket, routeSocket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun purgeConnectionRoute(clientSocket: Socket, routeSocket: Socket){
|
||||||
|
clientSocket.forceClose()
|
||||||
|
routeSocket.forceClose()
|
||||||
|
clients.remove(clientSocket, routeSocket)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Socket.forceClose() = try{ close() }catch(t: Throwable){}
|
||||||
|
|
||||||
|
private fun Socket.forwardConnection(dest: Socket){
|
||||||
|
val from = getInputStream()
|
||||||
|
val to = dest.getOutputStream()
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (from.available() > 0) {
|
||||||
|
val read = from.read(buffer, 0, buffer.size)
|
||||||
|
if (read > 0) to.write(buffer, 0, read)
|
||||||
|
}
|
||||||
|
}catch(t: Throwable){
|
||||||
|
// Probably a disconnection tbh
|
||||||
|
purgeConnectionRoute(this, dest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun ServerSocket.acceptPassthrough(){
|
||||||
|
val client: Socket
|
||||||
|
try {
|
||||||
|
client = accept()
|
||||||
|
} catch (e: SocketTimeoutException) {
|
||||||
|
// Accepting clients timed out: no new clients
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a corresponding, outgoing connection for the new client
|
||||||
|
clients[client] = Socket(routeTo, routePort)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user