Files
libmc/example/network-engines/JavaSocketNetworkEngine.kt
T
2026-09-08 11:13:37 +08:00

89 lines
2.7 KiB
Kotlin

/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/7
*/
package engines
import cn.rtast.libmc.network.RawSocket
import cn.rtast.libmc.network.ReadChannel
import cn.rtast.libmc.network.SocketEngine
import cn.rtast.libmc.network.WriteChannel
import java.io.InputStream
import java.io.OutputStream
import java.net.InetSocketAddress
import java.net.Socket
class JavaSocketEngine : SocketEngine {
override fun create(host: String, port: Int): RawSocket = JavaNetworkSocket(host, port)
}
class JavaNetworkSocket(
private val host: String,
private val port: Int,
private val connectTimeoutMs: Int = 10000,
) : RawSocket {
private lateinit var socket: Socket
private lateinit var readChannel: JavaReadChannel
private lateinit var writeChannel: JavaWriteChannel
override suspend fun connect() {
val s = Socket()
s.tcpNoDelay = true
s.connect(InetSocketAddress(host, port), connectTimeoutMs)
socket = s
readChannel = JavaReadChannel(s.getInputStream())
writeChannel = JavaWriteChannel(s.getOutputStream())
}
override fun openReadChannel(): ReadChannel = readChannel
override fun openWriteChannel(): WriteChannel = writeChannel
override fun close() {
if (::socket.isInitialized && !socket.isClosed) {
runCatching { socket.close() }
}
}
}
class JavaReadChannel(private val inputStream: InputStream) : ReadChannel {
override suspend fun readByte(): Byte {
val b = inputStream.read()
if (b == -1) throw IllegalStateException("Socket stream reached EOF while reading byte")
return b.toByte()
}
override suspend fun readBytes(length: Int): ByteArray {
val buffer = ByteArray(length)
readFullyInternal(buffer, 0, length)
return buffer
}
override suspend fun readFully(out: ByteArray, start: Int, end: Int) {
readFullyInternal(out, start, end - start)
}
private fun readFullyInternal(out: ByteArray, offset: Int, length: Int) {
var bytesRead = 0
while (bytesRead < length) {
val count = inputStream.read(out, offset + bytesRead, length - bytesRead)
if (count == -1) {
throw IllegalStateException("Socket stream closed unexpectedly (read $bytesRead of $length bytes)")
}
bytesRead += count
}
}
}
class JavaWriteChannel(private val outputStream: OutputStream) : WriteChannel {
override suspend fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) {
outputStream.write(value, startIndex, endIndex - startIndex)
}
override suspend fun flush() {
outputStream.flush()
}
}