105 lines
2.5 KiB
Kotlin
105 lines
2.5 KiB
Kotlin
package su.sonoma
|
|
|
|
import kotlinx.coroutines.*
|
|
import java.io.BufferedInputStream
|
|
import java.io.BufferedOutputStream
|
|
import java.net.ServerSocket
|
|
import java.net.Socket
|
|
import java.io.DataInputStream
|
|
|
|
fun startServer(address: String, port: Int, tun: String, outIntefrace: String) = runBlocking {
|
|
val tun = TunDevice(address, "awake0")
|
|
tun.addRoute()
|
|
tun.enableIpForwarding()
|
|
tun.enableMasquerade(outIntefrace)
|
|
|
|
val server = ServerSocket(port)
|
|
println("Server started on $port")
|
|
|
|
while (true) {
|
|
val client = server.accept()
|
|
println("${client.inetAddress} Client pairing")
|
|
|
|
launch(Dispatchers.IO) {
|
|
println("${client.inetAddress} Client connected")
|
|
|
|
try {
|
|
handle(client, tun)
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
}
|
|
|
|
launch(Dispatchers.IO) {
|
|
try {
|
|
forward(client, tun)
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fun handle(socket: Socket, tun: TunDevice) {
|
|
|
|
val input = BufferedInputStream(socket.getInputStream())
|
|
|
|
val buffer = ByteArray(1500)
|
|
|
|
while (true) {
|
|
|
|
val hi = input.read()
|
|
val lo = input.read()
|
|
|
|
if (hi == -1 || lo == -1) {
|
|
println("${socket.inetAddress} Client disconnected")
|
|
break
|
|
}
|
|
|
|
val len = (hi shl 8) or lo
|
|
|
|
//println("Message length: $len")
|
|
|
|
if (len <= 0 || len > buffer.size) {
|
|
println("Invalid packet size: $len")
|
|
break
|
|
}
|
|
|
|
var offset = 0
|
|
while (offset < len) {
|
|
val r = input.read(buffer, offset, len - offset)
|
|
|
|
//println("Read $r from client")
|
|
|
|
if (r == -1) {
|
|
println("${socket.inetAddress} Client closed stream")
|
|
return
|
|
}
|
|
offset += r
|
|
}
|
|
|
|
runCatching {
|
|
tun.output.write(buffer, 0, len)
|
|
tun.output.flush()
|
|
}
|
|
//println("Write in tun")
|
|
}
|
|
}
|
|
|
|
fun forward(socket: Socket, tun: TunDevice) {
|
|
|
|
val readBuffer = ByteArray(1500)
|
|
val output = BufferedOutputStream(socket.getOutputStream())
|
|
|
|
while (true) {
|
|
val responseLen = tun.input.read(readBuffer)
|
|
if (responseLen > 0) {
|
|
|
|
output.write((responseLen shr 8) and 0xFF)
|
|
output.write(responseLen and 0xFF)
|
|
|
|
output.write(readBuffer, 0, responseLen)
|
|
output.flush()
|
|
}
|
|
}
|
|
} |