Split rconlib and mcping

This commit is contained in:
2026-09-04 00:19:17 +08:00
parent 23e7a827db
commit 350b900aaa
38 files changed
+350 -268

No files matched your search

+6 -31
View File
@@ -1,46 +1,20 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
kotlin("multiplatform") version "2.4.10"
kotlin("multiplatform") version "2.4.10" apply false
id("maven-publish")
}
allprojects {
group = "cn.rtast.mcping"
version = providers.gradleProperty("libVersion").get()
repositories {
mavenCentral()
}
kotlin {
explicitApi()
linuxX64()
linuxArm64()
macosArm64()
mingwX64()
iosArm64()
iosSimulatorArm64()
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
sourceSets {
jvmMain.dependencies {
// no dependencies needed
}
nativeMain.dependencies {
implementation("io.ktor:ktor-network:3.5.2")
implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.9.1")
}
commonTest.dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0")
}
}
compilerOptions.freeCompilerArgs.addAll("-Xexpect-actual-classes")
}
subprojects {
pluginManager.apply("org.jetbrains.kotlin.multiplatform")
pluginManager.apply("maven-publish")
publishing {
repositories {
@@ -55,3 +29,4 @@ publishing {
}
}
}
}
+31
View File
@@ -0,0 +1,31 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
kotlin {
explicitApi()
linuxX64()
linuxArm64()
macosArm64()
mingwX64()
iosArm64()
iosSimulatorArm64()
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
sourceSets {
jvmMain.dependencies {
// no dependencies needed
}
nativeMain.dependencies {
implementation("io.ktor:ktor-network:3.5.2")
implementation("org.jetbrains.kotlinx:kotlinx-io-core:0.9.1")
}
commonTest.dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0")
}
}
compilerOptions.freeCompilerArgs.addAll("-Xexpect-actual-classes")
}
@@ -0,0 +1,28 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
@Suppress("CLASSNAME")
public expect class _Buffer {
public constructor()
public constructor(bytes: ByteArray)
public fun writeByte(value: Byte)
public fun writeShort(value: Short)
public fun writeLong(value: Long)
public fun writeBytes(bytes: ByteArray)
public fun readByte(): Byte
public fun readShort(): Short
public fun readLong(): Long
public fun readBytes(length: Int): ByteArray
public fun toByteArray(): ByteArray
public val size: Int
}
public fun ByteArray.wrap(): _Buffer = _Buffer(this)
@@ -0,0 +1,22 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
@Suppress("CLASSNAME")
public expect class _ReadChannel {
public fun readByte(): Byte
public fun readBytes(length: Int): ByteArray
public fun readFully(out: ByteArray, start: Int = 0, end: Int = out.size)
public fun readLong(): Long
}
@Suppress("CLASSNAME")
public expect class _WriteChannel {
public fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size)
public fun flush()
}
@@ -0,0 +1,21 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
@Suppress("CLASSNAME")
public expect class _Socket public constructor(host: String, port: Int, context: PingContext) {
public fun openReadChannel(): _ReadChannel
public fun openWriteChannel(): _WriteChannel
public fun close()
}
@Suppress("CLASSNAME")
public expect class _UdpSocket public constructor(host: String, port: Int, context: PingContext) {
public fun sendAndReceive(data: ByteArray): ByteArray
public fun close()
}
@@ -8,29 +8,29 @@ package cn.rtast.mcping.platform
import java.io.ByteArrayOutputStream
internal actual class PlatformBuffer {
@Suppress("CLASSNAME")
public actual class _Buffer {
private val outStream = ByteArrayOutputStream()
private var readBuffer: ByteArray? = null
private var readOffset = 0
actual constructor()
actual constructor(bytes: ByteArray) {
public actual constructor()
public actual constructor(bytes: ByteArray) {
this.readBuffer = bytes
outStream.write(bytes)
}
actual fun writeByte(value: Byte) {
public actual fun writeByte(value: Byte) {
outStream.write(value.toInt())
}
actual fun writeShort(value: Short) {
public actual fun writeShort(value: Short) {
val v = value.toInt()
outStream.write(v shr 8)
outStream.write(v)
}
actual fun writeLong(value: Long) {
public actual fun writeLong(value: Long) {
outStream.write((value shr 56).toInt())
outStream.write((value shr 48).toInt())
outStream.write((value shr 40).toInt())
@@ -41,7 +41,7 @@ internal actual class PlatformBuffer {
outStream.write(value.toInt())
}
actual fun writeBytes(bytes: ByteArray) {
public actual fun writeBytes(bytes: ByteArray) {
outStream.write(bytes)
}
@@ -54,19 +54,19 @@ internal actual class PlatformBuffer {
return buf
}
actual fun readByte(): Byte {
public actual fun readByte(): Byte {
val array = ensureReadArray()
if (readOffset >= array.size) throw IndexOutOfBoundsException("Buffer underflow")
return array[readOffset++]
}
actual fun readShort(): Short {
public actual fun readShort(): Short {
val b1 = readByte().toInt() and 0xFF
val b2 = readByte().toInt() and 0xFF
return ((b1 shl 8) or b2).toShort()
}
actual fun readLong(): Long {
public actual fun readLong(): Long {
return (readByte().toLong() and 0xFF shl 56) or
(readByte().toLong() and 0xFF shl 48) or
(readByte().toLong() and 0xFF shl 40) or
@@ -77,7 +77,7 @@ internal actual class PlatformBuffer {
(readByte().toLong() and 0xFF)
}
actual fun readBytes(length: Int): ByteArray {
public actual fun readBytes(length: Int): ByteArray {
val array = ensureReadArray()
if (readOffset + length > array.size) throw IndexOutOfBoundsException("Buffer underflow")
val result = array.copyOfRange(readOffset, readOffset + length)
@@ -85,8 +85,8 @@ internal actual class PlatformBuffer {
return result
}
actual fun toByteArray(): ByteArray = outStream.toByteArray()
public actual fun toByteArray(): ByteArray = outStream.toByteArray()
actual val size: Int
public actual val size: Int
get() = outStream.size()
}
@@ -11,16 +11,17 @@ import java.io.EOFException
import java.io.InputStream
import java.io.OutputStream
internal actual class ReadChannel {
@Suppress("CLASSNAME")
public actual class _ReadChannel {
private val _inputStream: InputStream
constructor(inputStream: InputStream) {
public constructor(inputStream: InputStream) {
_inputStream = inputStream
}
actual fun readByte(): Byte = _inputStream.read().toByte()
actual fun readBytes(length: Int): ByteArray = _inputStream.readNBytes(length)
actual fun readFully(out: ByteArray, start: Int, end: Int) {
public actual fun readByte(): Byte = _inputStream.read().toByte()
public actual fun readBytes(length: Int): ByteArray = _inputStream.readNBytes(length)
public actual fun readFully(out: ByteArray, start: Int, end: Int) {
var bytesRead = 0
val length = end - start
while (bytesRead < length) {
@@ -30,7 +31,7 @@ internal actual class ReadChannel {
}
}
actual fun readLong(): Long {
public actual fun readLong(): Long {
val bytes = ByteArray(8)
var read = 0
while (read < 8) {
@@ -49,17 +50,18 @@ internal actual class ReadChannel {
}
}
internal actual class WriteChannel {
@Suppress("CLASSNAME")
public actual class _WriteChannel {
private val _outputStream: OutputStream
constructor(outputStream: OutputStream) {
public constructor(outputStream: OutputStream) {
_outputStream = outputStream
}
actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) =
public actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit =
_outputStream.write(value, startIndex, endIndex - startIndex)
actual fun flush() = _outputStream.flush()
public actual fun flush(): Unit = _outputStream.flush()
}
private fun InputStream.readNBytes(length: Int): ByteArray {
@@ -11,21 +11,23 @@ import java.net.DatagramSocket
import java.net.InetSocketAddress
import java.net.Socket as JvmSocket
internal actual class Socket internal actual constructor(host: String, port: Int, context: PingContext) {
@Suppress("CLASSNAME")
public actual class _Socket public actual constructor(host: String, port: Int, context: PingContext) {
private val socket = JvmSocket(host, port)
actual fun openReadChannel(): ReadChannel = ReadChannel(socket.getInputStream())
actual fun openWriteChannel(): WriteChannel = WriteChannel(socket.getOutputStream())
actual fun close() = socket.close()
public actual fun openReadChannel(): _ReadChannel = _ReadChannel(socket.getInputStream())
public actual fun openWriteChannel(): _WriteChannel = _WriteChannel(socket.getOutputStream())
public actual fun close(): Unit = socket.close()
}
internal actual class UdpSocket internal actual constructor(host: String, port: Int, context: PingContext) {
@Suppress("CLASSNAME")
public actual class _UdpSocket public actual constructor(host: String, port: Int, context: PingContext) {
private val socket = DatagramSocket().apply {
soTimeout = 3000
connect(InetSocketAddress(host, port))
}
actual fun sendAndReceive(data: ByteArray): ByteArray {
public actual fun sendAndReceive(data: ByteArray): ByteArray {
socket.send(DatagramPacket(data, data.size))
val buf = ByteArray(2048)
@@ -34,5 +36,5 @@ internal actual class UdpSocket internal actual constructor(host: String, port:
return buf.copyOf(receivePacket.length)
}
actual fun close() = socket.close()
public actual fun close(): Unit = socket.close()
}
@@ -0,0 +1,38 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
import kotlinx.io.Buffer
import kotlinx.io.readByteArray
@Suppress("CLASSNAME")
public actual class _Buffer {
private val _delegateBuf: Buffer
public actual constructor() {
_delegateBuf = Buffer()
}
public actual constructor(bytes: ByteArray) {
_delegateBuf = Buffer().apply { write(bytes) }
}
public actual fun writeByte(value: Byte): Unit = _delegateBuf.writeByte(value)
public actual fun writeShort(value: Short): Unit = _delegateBuf.writeShort(value)
public actual fun writeLong(value: Long): Unit = _delegateBuf.writeLong(value)
public actual fun writeBytes(bytes: ByteArray): Unit = _delegateBuf.write(bytes)
public actual fun readByte(): Byte = _delegateBuf.readByte()
public actual fun readShort(): Short = _delegateBuf.readShort()
public actual fun readLong(): Long = _delegateBuf.readLong()
public actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length)
public actual fun toByteArray(): ByteArray = _delegateBuf.peek().readByteArray()
public actual val size: Int
get() = _delegateBuf.size.toInt()
}
@@ -0,0 +1,40 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
import io.ktor.utils.io.*
import kotlinx.coroutines.runBlocking
@Suppress("CLASSNAME")
public actual class _ReadChannel {
private val _readChannel: ByteReadChannel
public constructor(readChannel: ByteReadChannel) {
_readChannel = readChannel
}
public actual fun readByte(): Byte = runBlocking { _readChannel.readByte() }
public actual fun readBytes(length: Int): ByteArray = runBlocking { _readChannel.readByteArray(length) }
public actual fun readFully(out: ByteArray, start: Int, end: Int): Unit =
runBlocking { _readChannel.readFully(out, start, end) }
public actual fun readLong(): Long = runBlocking { _readChannel.readLong() }
}
@Suppress("CLASSNAME")
public actual class _WriteChannel {
private val _writeChannel: ByteWriteChannel
public constructor(writeChannel: ByteWriteChannel) {
_writeChannel = writeChannel
}
public actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int): Unit =
runBlocking { _writeChannel.writeFully(value, startIndex, endIndex) }
public actual fun flush(): Unit = runBlocking { _writeChannel.flush() }
}
@@ -11,34 +11,36 @@ import io.ktor.utils.io.core.*
import kotlinx.coroutines.runBlocking
import kotlinx.io.readByteArray
internal actual class Socket internal actual constructor(host: String, port: Int, context: PingContext) {
@Suppress("CLASSNAME")
public actual class _Socket public actual constructor(host: String, port: Int, context: PingContext) {
private val ctx = context
private val socket = runBlocking { aSocket(ctx._selectorManager).tcp().connect(host, port) }
actual fun openReadChannel(): ReadChannel = ReadChannel(socket.openReadChannel())
actual fun openWriteChannel(): WriteChannel =
WriteChannel(socket.openWriteChannel(autoFlush = true))
public actual fun openReadChannel(): _ReadChannel = _ReadChannel(socket.openReadChannel())
public actual fun openWriteChannel(): _WriteChannel =
_WriteChannel(socket.openWriteChannel(autoFlush = true))
actual fun close() {
public actual fun close() {
socket.close()
if (ctx._autoCloseSelectorManager) ctx._selectorManager.close()
}
}
internal actual class UdpSocket internal actual constructor(host: String, port: Int, context: PingContext) {
@Suppress("CLASSNAME")
public actual class _UdpSocket public actual constructor(host: String, port: Int, context: PingContext) {
private val ctx = context
// use bind to create an unconnected socket
private val socket = runBlocking { aSocket(ctx._selectorManager).udp().bind() }
private val remoteAddress = InetSocketAddress(host, port)
actual fun sendAndReceive(data: ByteArray): ByteArray = runBlocking {
public actual fun sendAndReceive(data: ByteArray): ByteArray = runBlocking {
val packet = buildPacket { writeFully(data) }
socket.send(Datagram(packet, remoteAddress))
socket.receive().packet.readByteArray()
}
actual fun close() {
public actual fun close() {
socket.close()
if (ctx._autoCloseSelectorManager) ctx._selectorManager.close()
}
+24
View File
@@ -0,0 +1,24 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
kotlin {
explicitApi()
linuxX64()
linuxArm64()
macosArm64()
mingwX64()
iosArm64()
iosSimulatorArm64()
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
sourceSets {
commonMain.dependencies {
implementation(project(":common"))
}
commonTest.dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0")
}
}
}
@@ -7,9 +7,8 @@
package cn.rtast.mcping.bedrock
import cn.rtast.mcping.platform.PlatformBuffer
import cn.rtast.mcping.platform._Buffer
import kotlin.random.Random
import kotlin.time.Clock
private val rakNetMagic = byteArrayOf(
0x00, 0xFF.toByte(),
@@ -26,7 +25,7 @@ internal interface MinecraftBedrockPacket {
val time: Long
val magic: ByteArray
fun writePayload(buffer: PlatformBuffer)
fun writePayload(buffer: _Buffer)
}
internal data class BedrockRequestPacket(
@@ -36,7 +35,7 @@ internal data class BedrockRequestPacket(
) : MinecraftBedrockPacket {
override val packetId: Byte = 0x01
override fun writePayload(buffer: PlatformBuffer) {
override fun writePayload(buffer: _Buffer) {
buffer.writeByte(packetId)
buffer.writeLong(time)
buffer.writeBytes(magic)
@@ -71,7 +70,7 @@ internal data class BedrockResponsePacket(
val stringLength: Short,
val payload: String,
) : MinecraftBedrockPacket {
override fun writePayload(buffer: PlatformBuffer) {}
override fun writePayload(buffer: _Buffer) {}
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -0,0 +1,17 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.bedrock
import cn.rtast.mcping.platform._Buffer
import cn.rtast.mcping.platform._UdpSocket
internal fun _UdpSocket.sendPacket(packet: MinecraftBedrockPacket): ByteArray {
val buf = _Buffer()
packet.writePayload(buf)
return sendAndReceive(buf.toByteArray())
}
@@ -9,12 +9,12 @@ package cn.rtast.mcping.bedrock
import cn.rtast.mcping.PingResponse
import cn.rtast.mcping.platform.PingContext
import cn.rtast.mcping.platform.UdpSocket
import cn.rtast.mcping.platform._UdpSocket
import cn.rtast.mcping.platform.wrap
import kotlin.time.Clock
internal fun pingBedrockServer(host: String, port: Int, context: PingContext): PingResponse {
val socket = UdpSocket(host, port, context)
val socket = _UdpSocket(host, port, context)
return try {
val sendTime = Clock.System.now().toEpochMilliseconds()
val packet = BedrockRequestPacket(sendTime)
@@ -6,11 +6,11 @@
package cn.rtast.mcping.java
import cn.rtast.mcping.platform.PlatformBuffer
import cn.rtast.mcping.platform.ReadChannel
import cn.rtast.mcping.platform._Buffer
import cn.rtast.mcping.platform._ReadChannel
internal fun PlatformBuffer.writeVarInt(value: Int) {
internal fun _Buffer.writeVarInt(value: Int) {
var v = value
while (true) {
if ((v and 0x7F.inv()) == 0) {
@@ -22,7 +22,7 @@ internal fun PlatformBuffer.writeVarInt(value: Int) {
}
}
internal fun ReadChannel.readVarInt(): Int {
internal fun _ReadChannel.readVarInt(): Int {
var value = 0
var position = 0
while (true) {
@@ -35,13 +35,13 @@ internal fun ReadChannel.readVarInt(): Int {
return value
}
internal fun PlatformBuffer.writeMcString(value: String) {
internal fun _Buffer.writeMcString(value: String) {
val bytes = value.encodeToByteArray()
this.writeVarInt(bytes.size)
this.writeBytes(bytes)
}
internal fun ReadChannel.readMcString(): String {
internal fun _ReadChannel.readMcString(): String {
val length = this.readVarInt()
val bytes = this.readBytes(length)
return bytes.decodeToString()
@@ -7,12 +7,12 @@
package cn.rtast.mcping.java
import cn.rtast.mcping.platform.PlatformBuffer
import cn.rtast.mcping.platform._Buffer
internal interface MinecraftPacket {
val packetId: Int
fun writePayload(buffer: PlatformBuffer)
fun writePayload(buffer: _Buffer)
}
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Handshake
@@ -25,7 +25,7 @@ internal data class HandshakePacket(
) : MinecraftPacket {
override val packetId: Int = 0x00
override fun writePayload(buffer: PlatformBuffer) {
override fun writePayload(buffer: _Buffer) {
buffer.writeVarInt(protocolVersion)
buffer.writeMcString(serverAddress)
// write UShort
@@ -39,10 +39,10 @@ internal data class HandshakePacket(
// ref https://minecraft.wiki/w/Java_Edition_protocol/Packets#Status
internal data object StatusRequestPacket : MinecraftPacket {
override val packetId: Int = 0x00
override fun writePayload(buffer: PlatformBuffer) {}
override fun writePayload(buffer: _Buffer) {}
}
internal data class PingPacket(val currentTime: Long) : MinecraftPacket {
override val packetId: Int = 0x01
override fun writePayload(buffer: PlatformBuffer) = buffer.writeLong(currentTime)
override fun writePayload(buffer: _Buffer) = buffer.writeLong(currentTime)
}
@@ -7,14 +7,14 @@
package cn.rtast.mcping.java
import cn.rtast.mcping.platform.PlatformBuffer
import cn.rtast.mcping.platform.WriteChannel
import cn.rtast.mcping.platform._Buffer
import cn.rtast.mcping.platform._WriteChannel
internal fun WriteChannel.sendPacket(packet: MinecraftPacket) {
val bodyBuffer = PlatformBuffer()
internal fun _WriteChannel.sendPacket(packet: MinecraftPacket) {
val bodyBuffer = _Buffer()
bodyBuffer.writeVarInt(packet.packetId)
packet.writePayload(bodyBuffer)
val frameBuffer = PlatformBuffer()
val frameBuffer = _Buffer()
frameBuffer.writeVarInt(bodyBuffer.size)
frameBuffer.writeBytes(bodyBuffer.toByteArray())
val bytes = frameBuffer.toByteArray()
@@ -9,11 +9,11 @@ package cn.rtast.mcping.java
import cn.rtast.mcping.PingResponse
import cn.rtast.mcping.platform.PingContext
import cn.rtast.mcping.platform.Socket
import cn.rtast.mcping.platform._Socket
import kotlin.time.Clock
internal fun pingJavaServer(host: String, port: Int, context: PingContext): PingResponse {
val socket = Socket(host, port, context)
val socket = _Socket(host, port, context)
val receiveChannel = socket.openReadChannel()
val sendChannel = socket.openWriteChannel()
+24
View File
@@ -0,0 +1,24 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
kotlin {
explicitApi()
linuxX64()
linuxArm64()
macosArm64()
mingwX64()
iosArm64()
iosSimulatorArm64()
jvm { compilerOptions.jvmTarget = JvmTarget.JVM_1_8 }
sourceSets {
commonMain.dependencies {
implementation(project(":common"))
}
commonTest.dependencies {
implementation(kotlin("test"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.11.0")
}
}
}
@@ -0,0 +1,9 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/4
*/
package cn.rtast.mcping.rconlib
+4
View File
@@ -2,3 +2,7 @@ plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "mcping"
include(":mcping")
include(":rconlib")
include(":common")
@@ -1,17 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.bedrock
import cn.rtast.mcping.platform.PlatformBuffer
import cn.rtast.mcping.platform.UdpSocket
internal fun UdpSocket.sendPacket(packet: MinecraftBedrockPacket): ByteArray {
val buf = PlatformBuffer()
packet.writePayload(buf)
return sendAndReceive(buf.toByteArray())
}
@@ -1,27 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
internal expect class PlatformBuffer {
constructor()
constructor(bytes: ByteArray)
fun writeByte(value: Byte)
fun writeShort(value: Short)
fun writeLong(value: Long)
fun writeBytes(bytes: ByteArray)
fun readByte(): Byte
fun readShort(): Short
fun readLong(): Long
fun readBytes(length: Int): ByteArray
fun toByteArray(): ByteArray
val size: Int
}
internal fun ByteArray.wrap(): PlatformBuffer = PlatformBuffer(this)
@@ -1,20 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
internal expect class ReadChannel {
fun readByte(): Byte
fun readBytes(length: Int): ByteArray
fun readFully(out: ByteArray, start: Int = 0, end: Int = out.size)
fun readLong(): Long
}
internal expect class WriteChannel {
fun writeFully(value: ByteArray, startIndex: Int = 0, endIndex: Int = value.size)
fun flush()
}
@@ -1,19 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
internal expect class Socket internal constructor(host: String, port: Int, context: PingContext) {
fun openReadChannel(): ReadChannel
fun openWriteChannel(): WriteChannel
fun close()
}
internal expect class UdpSocket internal constructor(host: String, port: Int, context: PingContext) {
fun sendAndReceive(data: ByteArray): ByteArray
fun close()
}
@@ -1,37 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
import kotlinx.io.Buffer
import kotlinx.io.readByteArray
internal actual class PlatformBuffer {
private val _delegateBuf: Buffer
actual constructor() {
_delegateBuf = Buffer()
}
actual constructor(bytes: ByteArray) {
_delegateBuf = Buffer().apply { write(bytes) }
}
actual fun writeByte(value: Byte) = _delegateBuf.writeByte(value)
actual fun writeShort(value: Short) = _delegateBuf.writeShort(value)
actual fun writeLong(value: Long) = _delegateBuf.writeLong(value)
actual fun writeBytes(bytes: ByteArray) = _delegateBuf.write(bytes)
actual fun readByte(): Byte = _delegateBuf.readByte()
actual fun readShort(): Short = _delegateBuf.readShort()
actual fun readLong(): Long = _delegateBuf.readLong()
actual fun readBytes(length: Int): ByteArray = _delegateBuf.readByteArray(length)
actual fun toByteArray(): ByteArray = _delegateBuf.peek().readByteArray()
actual val size: Int
get() = _delegateBuf.size.toInt()
}
@@ -1,36 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/3
*/
package cn.rtast.mcping.platform
import io.ktor.utils.io.*
import kotlinx.coroutines.runBlocking
internal actual class ReadChannel {
private val _readChannel: ByteReadChannel
constructor(readChannel: ByteReadChannel) {
_readChannel = readChannel
}
actual fun readByte(): Byte = runBlocking { _readChannel.readByte() }
actual fun readBytes(length: Int): ByteArray = runBlocking { _readChannel.readByteArray(length) }
actual fun readFully(out: ByteArray, start: Int, end: Int) = runBlocking { _readChannel.readFully(out, start, end) }
actual fun readLong(): Long = runBlocking { _readChannel.readLong() }
}
internal actual class WriteChannel {
private val _writeChannel: ByteWriteChannel
constructor(writeChannel: ByteWriteChannel) {
_writeChannel = writeChannel
}
actual fun writeFully(value: ByteArray, startIndex: Int, endIndex: Int) =
runBlocking { _writeChannel.writeFully(value, startIndex, endIndex) }
actual fun flush() = runBlocking { _writeChannel.flush() }
}