Fix some clientbound message bugs

send signed message{wip}
This commit is contained in:
2026-09-12 01:03:05 +08:00
parent b2ea685a9a
commit 480d0089e6
37 files changed
+689 -1206

No files matched your search

@@ -0,0 +1,12 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/7
*/
package cn.rtast.libmc.context
public interface HttpClientProvider {
public suspend fun post(url: String, headers: Map<String, String>?, body: String?): String
}
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.crypto
package cn.rtast.libmc.context
public interface NetworkChannelCipher {
public fun encrypt(buffer: ByteArray, offset: Int, length: Int)
@@ -0,0 +1,29 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/7
*/
package cn.rtast.libmc.context
import cn.rtast.libmc.network.SocketContext
import cn.rtast.libmc.network.SocketEngine
public data class ProtocolContext(
val httpClientProvider: HttpClientProvider?,
override val socketEngine: SocketEngine,
) : SocketContext()
public class ProtocolContextBuilder(private val onlineMode: Boolean) {
public lateinit var httpClientProvider: HttpClientProvider
public lateinit var socketEngine: SocketEngine
public fun build(): ProtocolContext =
ProtocolContext(
httpClientProvider = if (onlineMode) {
if (::httpClientProvider.isInitialized) httpClientProvider else error("authProvider is required in online mode")
} else if (::httpClientProvider.isInitialized) httpClientProvider else null,
socketEngine = if (::socketEngine.isInitialized) socketEngine else error("SocketEngine is not configured"),
)
}
@@ -1,12 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/7
*/
package cn.rtast.libmc.crypto
public fun interface AuthenticationProvider {
public suspend fun joinServer(url: String, accessToken: String, uuid: String, serverIdHash: String)
}
@@ -1,38 +0,0 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/7
*/
package cn.rtast.libmc.crypto
import cn.rtast.libmc.network.SocketContext
import cn.rtast.libmc.network.SocketEngine
public data class ProtocolContext(
val authProvider: AuthenticationProvider?,
override val engine: SocketEngine,
) : SocketContext()
public class ProtocolContextBuilder(private val onlineMode: Boolean) {
public lateinit var authProvider: AuthenticationProvider
public lateinit var socketEngine: SocketEngine
public fun build(): ProtocolContext =
ProtocolContext(
authProvider = if (onlineMode) {
if (::authProvider.isInitialized) authProvider else error("authProvider is required in online mode")
} else if (::authProvider.isInitialized) authProvider else null,
engine = if (::socketEngine.isInitialized) socketEngine else error("SocketEngine is not configured"),
)
}
public fun interface RSA1024Encryptor {
public fun encrypt(key: ByteArray, data: ByteArray): ByteArray
}
public fun interface Sha1Hasher {
public fun hash(serverId: String, secretKey: ByteArray, publicKey: ByteArray): String
}
@@ -7,12 +7,12 @@
package cn.rtast.libmc.network
import cn.rtast.libmc.crypto.ProtocolContextBuilder
import cn.rtast.libmc.context.ProtocolContextBuilder
public abstract class SocketContext {
public abstract val engine: SocketEngine
public abstract val socketEngine: SocketEngine
public fun createSocket(host: String, port: Int): RawSocket = engine.create(host, port)
public fun createSocket(host: String, port: Int): RawSocket = socketEngine.create(host, port)
}
public fun (ProtocolContextBuilder.() -> Unit).withCustom(
@@ -0,0 +1,114 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/12
*/
package cn.rtast.libmc.serialization
public object LiteralJsonParser {
public fun extractString(json: String, keyPath: List<String>): String? {
var currentScope = json
for (i in keyPath.indices) {
val key = keyPath[i]
val value = extractRawValue(currentScope, key) ?: return null
if (i == keyPath.lastIndex) return parseJsonString(value)
currentScope = value
}
return null
}
private fun extractRawValue(json: String, targetKey: String): String? {
val keyPattern = "\"$targetKey\""
val keyIndex = json.indexOf(keyPattern)
if (keyIndex == -1) return null
val colonIndex = json.indexOf(':', keyIndex + keyPattern.length)
if (colonIndex == -1) return null
var startIndex = colonIndex + 1
while (startIndex < json.length && json[startIndex].isWhitespace()) startIndex++
if (startIndex >= json.length) return null
val firstChar = json[startIndex]
return when (firstChar) {
'"' -> extractStringLiteral(json, startIndex)
'{' -> extractObjectLiteral(json, startIndex)
else -> null
}
}
private fun extractStringLiteral(json: String, startIndex: Int): String? {
var inEscape = false
for (i in startIndex + 1 until json.length) {
val c = json[i]
if (inEscape) {
inEscape = false
} else if (c == '\\') {
inEscape = true
} else if (c == '"') return json.substring(startIndex, i + 1)
}
return null
}
private fun extractObjectLiteral(json: String, startIndex: Int): String? {
var depth = 0
var inString = false
var inEscape = false
for (i in startIndex until json.length) {
val c = json[i]
if (inString) {
if (inEscape) {
inEscape = false
} else if (c == '\\') {
inEscape = true
} else if (c == '"') {
inString = false
}
} else {
when (c) {
'"' -> inString = true
'{' -> depth++
'}' -> {
depth--
if (depth == 0) return json.substring(startIndex, i + 1)
}
}
}
}
return null
}
private fun parseJsonString(rawJsonString: String): String? {
if (rawJsonString.length < 2 || !rawJsonString.startsWith('"') || !rawJsonString.endsWith('"')) return null
val content = rawJsonString.substring(1, rawJsonString.length - 1)
val sb = StringBuilder()
var i = 0
while (i < content.length) {
val c = content[i]
if (c == '\\' && i + 1 < content.length) {
when (val next = content[i + 1]) {
'n' -> sb.append('\n')
'r' -> sb.append('\r')
't' -> sb.append('\t')
'"' -> sb.append('"')
'\\' -> sb.append('\\')
'/' -> sb.append('/')
'u' -> {
if (i + 5 < content.length) {
val hex = content.substring(i + 2, i + 6)
sb.append(hex.toInt(16).toChar())
i += 5
} else {
sb.append(c)
}
}
else -> sb.append(next)
}
i += 2
} else {
sb.append(c)
i++
}
}
return sb.toString()
}
}
@@ -0,0 +1,39 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/12
*/
package test
import cn.rtast.libmc.serialization.LiteralJsonParser
import kotlin.test.Test
class TestJsonParser {
@Test
fun testJsonParser() {
val input = """
{
"keyPair": {
"privateKey": "-----BEGIN RSA PRIVATE KEY-----",
"publicKey": "-----BEGIN RSA PUBLIC KEY-----"
},
"publicKeySignature": "",
"publicKeySignatureV2": "",
"expiresAt": "2026-09-13T03:52:50.501218Z",
"refreshedAfter": "2026-09-12T19:52:50.501218Z"
}
""".trimIndent()
println(LiteralJsonParser.extractString(input, listOf("keyPair", "privateKey")))
}
}