Commit 77ddb6f7 authored by Him188's avatar Him188

QQA Debugging update

parent 8eb3daca
package net.mamoe.mirai.qqandroid.network package net.mamoe.mirai.qqandroid.network
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.*
import kotlinx.io.core.use import kotlinx.io.pool.ObjectPool
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
...@@ -14,11 +14,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket ...@@ -14,11 +14,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.RegPushReason import net.mamoe.mirai.qqandroid.network.protocol.packet.login.RegPushReason
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
import net.mamoe.mirai.utils.LockFreeLinkedList import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.unsafeWeakRef
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
...@@ -46,25 +43,137 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -46,25 +43,137 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>() SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>()
} }
internal fun launchPacketProcessor(rawInput: ByteReadPacket): Job = launch(CoroutineName("Incoming Packet handler")) { /**
rawInput.debugPrint("Received").use { input -> * 单线程处理包的接收, 分割和连接.
if (input.remaining == 0L) { */
bot.logger.error("Empty packet received. Consider if bad packet was sent.") @Suppress("PrivatePropertyName")
return@launch private val PacketReceiveDispatcher = newCoroutineDispatcher(1)
/**
* 单线程处理包的解析 (协程挂起效率够)
*/
@Suppress("PrivatePropertyName")
private val PacketProcessDispatcher = newCoroutineDispatcher(1)
/**
* 缓存的包
*/
private var cachedPacket: ByteReadPacket? = null
/**
* 缓存的包还差多少长度
*/
private var expectingRemainingLength: Long = 0
/**
* 在 [PacketProcessDispatcher] 调度器中解析包内容.
* [input] 将会被 [ObjectPool.recycle].
*
* @param input 一个完整的包的内容, 去掉开头的 int 包长度
*/
fun parsePacketAsync(input: IoBuffer, pool: ObjectPool<IoBuffer> = IoBuffer.Pool): Job =
this.launch(PacketProcessDispatcher) {
try {
parsePacket(input)
} finally {
input.discard()
input.release(pool)
}
}
/**
* 在 [PacketProcessDispatcher] 调度器中解析包内容.
* [input] 将会被 [Input.close], 因此 [input] 不能为 [IoBuffer]
*
* @param input 一个完整的包的内容, 去掉开头的 int 包长度
*/
fun parsePacketAsync(input: Input): Job {
require(input !is IoBuffer) { "input cannot be IoBuffer" }
return this.launch(PacketProcessDispatcher) {
input.use { parsePacket(it) }
}
}
/**
* 解析包内容
* **注意**: 需要函数调用者 close 这个 [input]
*
* @param input 一个完整的包的内容, 去掉开头的 int 包长度
*/
suspend fun parsePacket(input: Input) {
KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int ->
if (PacketReceivedEvent(packet).broadcast().cancelled) {
return@parseIncomingPacket
} }
KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int -> packetListeners.forEach { listener ->
if (PacketReceivedEvent(packet).broadcast().cancelled) { if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) {
return@parseIncomingPacket listener.complete(packet)
} }
packetListeners.forEach { listener -> }
if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) { }
listener.complete(packet) }
}
/**
* 处理从服务器接收过来的包. 这些包可能是粘在一起的, 也可能是不完整的. 将会自动处理
*/
@UseExperimental(ExperimentalCoroutinesApi::class)
internal suspend fun processPacket(rawInput: ByteReadPacket): Unit = rawInput.debugPrint("Received").let { input: ByteReadPacket ->
if (input.remaining == 0L) {
return
}
if (cachedPacket == null) {
// 没有缓存
var length: Int = input.readInt() - 4
if (input.remaining == length.toLong()) {
// 捷径: 当包长度正好, 直接传递剩余数据.
parsePacketAsync(input)
return
}
// 循环所有完整的包
while (input.remaining > length) {
parsePacketAsync(input.readIoBuffer(length))
length = input.readInt() - 4
}
if (input.remaining != 0L) {
// 剩余的包长度不够, 缓存后接收下一个包
expectingRemainingLength = length - input.remaining
cachedPacket = input
} else {
cachedPacket = null // 表示包长度正好
}
} else {
// 有缓存
if (input.remaining >= expectingRemainingLength) {
// 剩余长度够, 连接上去, 处理这个包.
parsePacketAsync(buildPacket {
writePacket(cachedPacket!!)
writePacket(input, expectingRemainingLength)
})
cachedPacket = null // 缺少的长度已经给上了.
if (input.remaining != 0L) {
processPacket(input) // 继续处理剩下内容
}
} else {
// 剩余不够, 连接上去
expectingRemainingLength -= input.remaining
cachedPacket = buildPacket {
writePacket(cachedPacket!!)
writePacket(input)
} }
} }
} }
if (input.remaining == 0L) {
bot.logger.error("Empty packet received. Consider if bad packet was sent.")
return
}
} }
@UseExperimental(ExperimentalCoroutinesApi::class)
private suspend fun processReceive() { private suspend fun processReceive() {
while (channel.isOpen) { while (channel.isOpen) {
val rawInput = try { val rawInput = try {
...@@ -81,7 +190,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -81,7 +190,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
bot.logger.error("Caught unexpected exceptions", e) bot.logger.error("Caught unexpected exceptions", e)
continue continue
} }
launchPacketProcessor(rawInput) launch(context = PacketReceiveDispatcher + CoroutineName("Incoming Packet handler"), start = CoroutineStart.ATOMIC) {
processPacket(rawInput)
}
} }
} }
......
...@@ -62,16 +62,13 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( ...@@ -62,16 +62,13 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
// 00 00 08 E0 00 00 00 0A 01 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 B4 16 A6 D7 A3 E4 9E 53 99 CD 77 14 70 1F 51 3E 8B 79 F6 93 2B E0 92 E4 32 E2 87 6C 3A 9C 1B 29 87 CB 3C 60 45 9C 41 71 63 6A F6 99 FC 05 01 68 86 B3 6F 37 97 52 C5 D3 0E 66 B3 F6 40 CC EB 18 A3 AE 15 3E 31 B1 E9 7C 6F EC E4 4D 31 F1 1E 2C 0C 1C 45 66 CD F7 1B 90 11 9A D8 CE DD 6D 6C 63 9F EB CD 69 33 AF 6C 8E BA 8C CB C3 FF 27 A2 A6 C3 28 06 4A B5 79 79 12 AB 52 04 62 CA 7D 11 59 85 5C 0B D6 8D 2A E7 9C 04 97 62 7D 05 11 3E 2C 11 60 E3 E3 B3 DA 7A 7C 13 AF 22 01 53 80 69 D0 F9 C8 86 EC 25 8C F3 67 5C 82 45 08 FB 34 43 50 01 0E EA 43 77 D8 CF EC 55 E6 4E 66 5B 26 21 C9 E8 78 92 AE 5C 61 F0 5E 0B E7 34 1F 53 D6 EA 28 9C 02 1A E9 F0 55 61 4B 06 F8 56 3B AC 93 B2 2C CD 66 0D D1 18 CB BD 29 50 DE 0F 82 6D 28 63 AB 21 E1 6C BA B1 9F 69 A4 E3 C9 20 F8 11 82 39 04 2B 54 44 50 FA 2E 86 68 6D DC 5D 9E 18 F4 DD 19 09 BC CF E8 41 68 A3 8D 86 42 80 51 C4 C1 ED 54 DB 50 F5 1D A7 28 2A 0D E8 14 1A 4E F7 96 29 00 6C 9D 4A 2E 3E 7B 4C AC 20 78 F1 3C 70 6B 61 96 D7 EC 77 AD CB AD AF BB 47 C3 1F A0 6C 6C 9C 9F F3 6C EB 6C A4 D0 7F 2B E1 AA 68 26 99 B9 C8 A1 F5 C4 7E E7 E7 81 EE 66 00 96 33 49 C0 EE A2 F9 F6 52 C5 A6 5D EE 9D C5 E5 CE DA 31 FC FF 4B 02 97 68 3D 6A 99 4A CF 69 D9 F4 53 68 31 E7 32 2F 85 E7 7F 16 82 AE FA 73 D5 42 09 9C CB 53 26 79 41 63 80 B0 E2 6A 8B B9 C6 71 08 B4 2B E0 48 D3 C4 0F B0 00 D0 FA 8C 29 DE E9 71 6A D7 89 76 E7 5D 33 14 10 6F E2 44 6A A0 DC C1 CB F3 9A C3 13 CB D1 82 2C DF 34 68 79 E3 09 BD CC 2B 25 79 A8 E7 BE 29 6C 97 C3 D7 F4 0E CC 2B 74 71 02 BA 2B 5B 57 1B C2 C8 C2 BF 54 23 72 EA E4 38 54 20 7D 88 E4 39 7C C5 8A 1B C0 EC D2 1E 7D 1B 6B 7A BC EC 73 1E 53 4A 6F 4F EA F0 56 12 80 BD 0B 37 67 BD FD A8 29 23 2D 8E 66 7E 31 A9 F6 CE 7E BC 4F 38 D0 33 D4 C7 4A E9 43 9D 28 2E 8F 7C D5 81 F4 8C F9 6F 21 AC A1 08 FD F4 01 FB E8 CE 61 91 BE 68 5B E4 3A 5F F8 FB DA 5D 9B 2A AF E2 0C D3 A4 1F 42 90 96 E1 28 44 85 8D E1 CF 19 A9 47 04 8D 28 D9 B3 35 79 48 70 D9 ED 45 B6 24 B5 56 FA 1E DE 02 F3 EB 69 08 7D 24 9C 60 35 97 8D 13 4A 5A 57 BA B3 14 C1 EE 70 22 CA B2 65 F7 BB 3F A2 D9 14 AA 4C 52 E6 E4 10 D3 FD C6 2B DD BF C0 CF E5 35 57 9E 9F D0 77 C8 E6 EF 2B 8E 01 88 96 F8 68 95 A7 0D 58 81 30 60 88 44 CC 31 5B C1 D4 92 6E ED 17 CA 0A 01 69 90 4E 6A C0 D7 09 6C E5 33 64 CA 6E 5C 07 C3 AD 46 36 F9 DF DE B7 71 B2 87 CB 3D 76 C0 44 B8 6B 15 27 B2 03 99 C7 51 8A 00 35 C9 1C 76 55 32 AE 49 5A 34 6A 4E FD 20 7A 24 BF 34 E8 B4 18 BC 92 64 A1 F3 0A 2E 7B 00 EA B6 52 E7 AC 34 FD AE FF 1E 5D 6D D6 1F 6D 06 31 09 9D A9 9C 86 DB 5E 05 07 BA 4A 49 2B D2 7F EE 88 64 B2 6F 15 70 39 1B E9 57 6A 4E 29 4A A4 57 EA 80 3D 86 4C E9 F7 F5 2B C4 9F 35 62 76 09 0E 1C A4 99 50 99 82 2F 84 90 0E 9E 9F 75 C3 15 B0 61 34 D1 67 2D 30 16 FE D3 BF 59 6A B1 74 02 C4 EF 92 85 E0 16 4B 0C C5 9D 65 BB 5D 52 8F 52 5B 7C 7B 74 D9 EC 41 A9 5B FA 2D 95 D4 AE 5D F1 68 88 F6 82 ED 09 05 21 2E 5D 93 64 A0 96 15 64 A6 50 3C 03 2B FC 3E 80 89 90 62 CC D9 23 8E D7 BD 05 02 30 86 32 31 6A 5F F8 C4 BD 61 D0 CE B9 54 4E 93 E9 AE B9 4F 2B 98 DC 23 31 CC A8 06 89 A8 08 60 99 DC D4 81 98 13 C9 27 36 32 24 C1 B0 6B F0 3D EB CC 3B 32 5F 20 72 23 B3 DF 0B 48 3C 35 FD F1 FB DC 3E 2A BE B9 0F 42 56 F1 39 94 86 85 C6 1E A0 4C EC B8 69 45 5F 3D AB 3C 3B A2 70 61 91 9D 2C DD 6D C5 E9 EF 47 36 A6 A3 E0 96 C2 B8 EF 92 E9 E0 26 88 C6 B5 51 BA DE FD C5 BA 4C 6A 9A FE 6F DE B8 10 05 7F 9C 5D 40 11 39 75 CD 36 4F 6B A8 A1 94 57 5F 8F F2 D0 E2 36 A0 A4 24 05 FD 9E F5 51 93 C9 6E 5A 10 8D C3 33 2D E5 09 7A E0 DB 44 63 9C EA A5 ED BF 0B 98 32 F1 BA 04 96 F6 14 49 F1 F8 58 EA 6E 5E 5E 49 CA 2D E2 93 E6 AD 20 B2 CD 98 A7 3E BA 3E A8 // 00 00 08 E0 00 00 00 0A 01 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 B4 16 A6 D7 A3 E4 9E 53 99 CD 77 14 70 1F 51 3E 8B 79 F6 93 2B E0 92 E4 32 E2 87 6C 3A 9C 1B 29 87 CB 3C 60 45 9C 41 71 63 6A F6 99 FC 05 01 68 86 B3 6F 37 97 52 C5 D3 0E 66 B3 F6 40 CC EB 18 A3 AE 15 3E 31 B1 E9 7C 6F EC E4 4D 31 F1 1E 2C 0C 1C 45 66 CD F7 1B 90 11 9A D8 CE DD 6D 6C 63 9F EB CD 69 33 AF 6C 8E BA 8C CB C3 FF 27 A2 A6 C3 28 06 4A B5 79 79 12 AB 52 04 62 CA 7D 11 59 85 5C 0B D6 8D 2A E7 9C 04 97 62 7D 05 11 3E 2C 11 60 E3 E3 B3 DA 7A 7C 13 AF 22 01 53 80 69 D0 F9 C8 86 EC 25 8C F3 67 5C 82 45 08 FB 34 43 50 01 0E EA 43 77 D8 CF EC 55 E6 4E 66 5B 26 21 C9 E8 78 92 AE 5C 61 F0 5E 0B E7 34 1F 53 D6 EA 28 9C 02 1A E9 F0 55 61 4B 06 F8 56 3B AC 93 B2 2C CD 66 0D D1 18 CB BD 29 50 DE 0F 82 6D 28 63 AB 21 E1 6C BA B1 9F 69 A4 E3 C9 20 F8 11 82 39 04 2B 54 44 50 FA 2E 86 68 6D DC 5D 9E 18 F4 DD 19 09 BC CF E8 41 68 A3 8D 86 42 80 51 C4 C1 ED 54 DB 50 F5 1D A7 28 2A 0D E8 14 1A 4E F7 96 29 00 6C 9D 4A 2E 3E 7B 4C AC 20 78 F1 3C 70 6B 61 96 D7 EC 77 AD CB AD AF BB 47 C3 1F A0 6C 6C 9C 9F F3 6C EB 6C A4 D0 7F 2B E1 AA 68 26 99 B9 C8 A1 F5 C4 7E E7 E7 81 EE 66 00 96 33 49 C0 EE A2 F9 F6 52 C5 A6 5D EE 9D C5 E5 CE DA 31 FC FF 4B 02 97 68 3D 6A 99 4A CF 69 D9 F4 53 68 31 E7 32 2F 85 E7 7F 16 82 AE FA 73 D5 42 09 9C CB 53 26 79 41 63 80 B0 E2 6A 8B B9 C6 71 08 B4 2B E0 48 D3 C4 0F B0 00 D0 FA 8C 29 DE E9 71 6A D7 89 76 E7 5D 33 14 10 6F E2 44 6A A0 DC C1 CB F3 9A C3 13 CB D1 82 2C DF 34 68 79 E3 09 BD CC 2B 25 79 A8 E7 BE 29 6C 97 C3 D7 F4 0E CC 2B 74 71 02 BA 2B 5B 57 1B C2 C8 C2 BF 54 23 72 EA E4 38 54 20 7D 88 E4 39 7C C5 8A 1B C0 EC D2 1E 7D 1B 6B 7A BC EC 73 1E 53 4A 6F 4F EA F0 56 12 80 BD 0B 37 67 BD FD A8 29 23 2D 8E 66 7E 31 A9 F6 CE 7E BC 4F 38 D0 33 D4 C7 4A E9 43 9D 28 2E 8F 7C D5 81 F4 8C F9 6F 21 AC A1 08 FD F4 01 FB E8 CE 61 91 BE 68 5B E4 3A 5F F8 FB DA 5D 9B 2A AF E2 0C D3 A4 1F 42 90 96 E1 28 44 85 8D E1 CF 19 A9 47 04 8D 28 D9 B3 35 79 48 70 D9 ED 45 B6 24 B5 56 FA 1E DE 02 F3 EB 69 08 7D 24 9C 60 35 97 8D 13 4A 5A 57 BA B3 14 C1 EE 70 22 CA B2 65 F7 BB 3F A2 D9 14 AA 4C 52 E6 E4 10 D3 FD C6 2B DD BF C0 CF E5 35 57 9E 9F D0 77 C8 E6 EF 2B 8E 01 88 96 F8 68 95 A7 0D 58 81 30 60 88 44 CC 31 5B C1 D4 92 6E ED 17 CA 0A 01 69 90 4E 6A C0 D7 09 6C E5 33 64 CA 6E 5C 07 C3 AD 46 36 F9 DF DE B7 71 B2 87 CB 3D 76 C0 44 B8 6B 15 27 B2 03 99 C7 51 8A 00 35 C9 1C 76 55 32 AE 49 5A 34 6A 4E FD 20 7A 24 BF 34 E8 B4 18 BC 92 64 A1 F3 0A 2E 7B 00 EA B6 52 E7 AC 34 FD AE FF 1E 5D 6D D6 1F 6D 06 31 09 9D A9 9C 86 DB 5E 05 07 BA 4A 49 2B D2 7F EE 88 64 B2 6F 15 70 39 1B E9 57 6A 4E 29 4A A4 57 EA 80 3D 86 4C E9 F7 F5 2B C4 9F 35 62 76 09 0E 1C A4 99 50 99 82 2F 84 90 0E 9E 9F 75 C3 15 B0 61 34 D1 67 2D 30 16 FE D3 BF 59 6A B1 74 02 C4 EF 92 85 E0 16 4B 0C C5 9D 65 BB 5D 52 8F 52 5B 7C 7B 74 D9 EC 41 A9 5B FA 2D 95 D4 AE 5D F1 68 88 F6 82 ED 09 05 21 2E 5D 93 64 A0 96 15 64 A6 50 3C 03 2B FC 3E 80 89 90 62 CC D9 23 8E D7 BD 05 02 30 86 32 31 6A 5F F8 C4 BD 61 D0 CE B9 54 4E 93 E9 AE B9 4F 2B 98 DC 23 31 CC A8 06 89 A8 08 60 99 DC D4 81 98 13 C9 27 36 32 24 C1 B0 6B F0 3D EB CC 3B 32 5F 20 72 23 B3 DF 0B 48 3C 35 FD F1 FB DC 3E 2A BE B9 0F 42 56 F1 39 94 86 85 C6 1E A0 4C EC B8 69 45 5F 3D AB 3C 3B A2 70 61 91 9D 2C DD 6D C5 E9 EF 47 36 A6 A3 E0 96 C2 B8 EF 92 E9 E0 26 88 C6 B5 51 BA DE FD C5 BA 4C 6A 9A FE 6F DE B8 10 05 7F 9C 5D 40 11 39 75 CD 36 4F 6B A8 A1 94 57 5F 8F F2 D0 E2 36 A0 A4 24 05 FD 9E F5 51 93 C9 6E 5A 10 8D C3 33 2D E5 09 7A E0 DB 44 63 9C EA A5 ED BF 0B 98 32 F1 BA 04 96 F6 14 49 F1 F8 58 EA 6E 5E 5E 49 CA 2D E2 93 E6 AD 20 B2 CD 98 A7 3E BA 3E A8
/**
* full packet without length
*/
// do not inline. Exceptions thrown will not be reported correctly // do not inline. Exceptions thrown will not be reported correctly
suspend fun parseIncomingPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) = suspend fun parseIncomingPacket(bot: QQAndroidBot, rawInput: Input, consumer: PacketConsumer) =
rawInput.debugIfFail("Incoming packet") { rawInput.debugIfFail("Incoming packet") {
require(remaining < Int.MAX_VALUE) { "rawInput is too long" } require(remaining < Int.MAX_VALUE) { "rawInput is too long" }
val expectedLength = readUInt().toInt() - 4
if (expectedLength > 16e7) {
bot.logger.warning("Detect incomplete packet, ignoring.")
return@debugIfFail
}
check(remaining.toInt() == expectedLength) { "Invalid packet length. Expected $expectedLength, got ${this.remaining} Probably packets merged? " }
// login // login
val flag1 = readInt() val flag1 = readInt()
...@@ -88,12 +85,12 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( ...@@ -88,12 +85,12 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
//debugPrint("remaining") //debugPrint("remaining")
when (flag1) { when (flag1) {
0x0A -> parseLoginSsoPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer) 0x0A -> parseLoginSsoPacket(bot, if (flag2 == 2) decryptBy(DECRYPTER_16_ZERO) else decryptBy(bot.client.wLoginSigInfo.d2Key), consumer)
0x0B -> parseUniPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer) 0x0B -> parseUniPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
} }
} }
private suspend fun parseUniPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) = private fun parseUniPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
rawInput.debugIfFail("Login sso packet") { rawInput.debugIfFail("Login sso packet") {
readIoBuffer(readInt() - 4).withUse { readIoBuffer(readInt() - 4).withUse {
//00 01 4E 64 FF FF D8 E8 00 00 00 14 6E 65 65 64 20 41 32 20 61 6E 64 20 49 4D 45 49 00 00 00 04 00 00 00 08 60 7F B6 23 00 00 00 00 00 00 00 04 //00 01 4E 64 FF FF D8 E8 00 00 00 14 6E 65 65 64 20 41 32 20 61 6E 64 20 49 4D 45 49 00 00 00 04 00 00 00 08 60 7F B6 23 00 00 00 00 00 00 00 04
......
...@@ -68,8 +68,12 @@ private val shareKeyCalculatedByConstPubKey = ECDH.calculateShareKey( ...@@ -68,8 +68,12 @@ private val shareKeyCalculatedByConstPubKey = ECDH.calculateShareKey(
) )
fun main() { fun main() {
val data = """ val data = """
20da22db750806141ef448110800450001b45126400080060000c0a8030a71600dd0fe501f908b8c585508ceeec6501801fc448900000000018c0000000a0100000044e0e22a59327abb9ce80cf63be86694210344fab2f2b065d7785a32cacfa4075cd509f49cb37a075ad0685cbd472344bfdef1ede611c0ad81129be9e2d7e476d2000000000e31393934373031303231f00754574170e9a5d13ca9426984103d1813e22d9c2147f8da5a0af64f64e4ebffde9ce8bfda6c1f798364a1de449adc701595fdce57fa4643e5e14eb4444ad0aea85261a6d5ee90c42a29b5af461a971a7fe85ecf1ed0d582d1cce60d1c34f6a3dc74a75d2f525d590da954098a1a7a4973773195dd209e662cb5c1e0db69843aa75425993bdc8876f21fd9c875d25fa47b689ebc302f3087de8e4a9862cff283703237602e50fa6bb281e974315b70f04f436d8ae9c5d67e22af3495e64aada419940e63c8d0ddbb066fa3d2b8cb27209a687d782d4ec32e6505593625bf0de257d59332f779ed6edb849502591e2c37b983974dbc3ec4740dfd0a9244baf958219067ca7d435ec8bde8e57b36f04d31622a86cb9c8d59d81074c9af38d57f42bb331a0a15f9ac5e216ae54abe8f8a 20da22db750806141ef448110800450000d4512f400080060000c0a8030a71600dd0fe501f908b8c5c9908cf2416501801ff43a90000000000ac0000000b0100014f0d000000000e3139393437303130323193c94c8ce2871f6d5f6664df9e9231dedce5c7cb914cf5d616cf64af478aea9f210098e7f5efae9a952742b8fff704681885e5cc14a44e40d88910258f4a4a5cfcadd642cc159fdc475478475b18ba225cfad1c8bc2c5c828a9cc3ebaed1aa040d04b94f577fcfdb0861fd19754622733a242c5bcb37ca8597a2935d9910162111e44839b6787bb9be80058ad9c921c2
""".trimIndent() """.trimIndent()
.trim().split("\n").map { .trim().split("\n").map {
val bytes = it.trim().autoHexToBytes() val bytes = it.trim().autoHexToBytes()
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
package test package test
import net.mamoe.mirai.utils.cryptor.protoFieldNumber import net.mamoe.mirai.utils.cryptor.protoFieldNumber
import net.mamoe.mirai.utils.cryptor.protoType
intArrayOf(10, 18, 26, 34, 42, 50, 58, 66, 74).forEach { intArrayOf(8, 18, 26, 34, 80).forEach {
println(protoFieldNumber(it.toUInt())) println(protoFieldNumber(it.toUInt()).toString() + " -> " + protoType(it.toUInt()))
} }
\ No newline at end of file
...@@ -3,12 +3,15 @@ package net.mamoe.mirai.utils ...@@ -3,12 +3,15 @@ package net.mamoe.mirai.utils
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO import io.ktor.client.engine.cio.CIO
import io.ktor.util.KtorExperimentalAPI import io.ktor.util.KtorExperimentalAPI
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.DataInput import java.io.DataInput
import java.io.EOFException import java.io.EOFException
import java.io.InputStream import java.io.InputStream
import java.net.InetAddress import java.net.InetAddress
import java.security.MessageDigest import java.security.MessageDigest
import java.util.concurrent.Executors
import java.util.zip.CRC32 import java.util.zip.CRC32
import java.util.zip.Inflater import java.util.zip.Inflater
...@@ -91,4 +94,8 @@ actual fun ByteArray.unzip(): ByteArray { ...@@ -91,4 +94,8 @@ actual fun ByteArray.unzip(): ByteArray {
} }
inflater.end() inflater.end()
return output.toByteArray() return output.toByteArray()
}
actual fun newCoroutineDispatcher(threadCount: Int): CoroutineDispatcher {
return Executors.newFixedThreadPool(threadCount).asCoroutineDispatcher()
} }
\ No newline at end of file
...@@ -4,6 +4,7 @@ package net.mamoe.mirai.utils ...@@ -4,6 +4,7 @@ package net.mamoe.mirai.utils
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.util.date.GMTDate import io.ktor.util.date.GMTDate
import kotlinx.coroutines.CoroutineDispatcher
/** /**
* 时间戳 * 时间戳
...@@ -46,3 +47,5 @@ expect fun localIpAddress(): String ...@@ -46,3 +47,5 @@ expect fun localIpAddress(): String
* Ktor HttpClient. 不同平台使用不同引擎. * Ktor HttpClient. 不同平台使用不同引擎.
*/ */
expect val Http: HttpClient expect val Http: HttpClient
expect fun newCoroutineDispatcher(threadCount: Int): CoroutineDispatcher
\ No newline at end of file
...@@ -2,7 +2,10 @@ package net.mamoe.mirai.utils.io ...@@ -2,7 +2,10 @@ package net.mamoe.mirai.utils.io
import kotlinx.io.core.* import kotlinx.io.core.*
import kotlinx.io.pool.useInstance import kotlinx.io.pool.useInstance
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.DefaultLogger
import net.mamoe.mirai.utils.MiraiDebugAPI
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.withSwitch
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
...@@ -74,7 +77,7 @@ inline fun <R> Input.debugIfFail(name: String = "", onFail: (ByteArray) -> ByteR ...@@ -74,7 +77,7 @@ inline fun <R> Input.debugIfFail(name: String = "", onFail: (ByteArray) -> ByteR
ByteArrayPool.useInstance { ByteArrayPool.useInstance {
val count = this.readAvailable(it) val count = this.readAvailable(it)
try { try {
return block(it.toReadPacket(0, count)) return it.toReadPacket(0, count).use(block)
} catch (e: Throwable) { } catch (e: Throwable) {
onFail(it.take(count).toByteArray()).readAvailable(it) onFail(it.take(count).toByteArray()).readAvailable(it)
DebugLogger.debug("Error in ByteReadPacket $name=" + it.toUHexString(offset = 0, length = count)) DebugLogger.debug("Error in ByteReadPacket $name=" + it.toUHexString(offset = 0, length = count))
......
...@@ -4,15 +4,15 @@ package net.mamoe.mirai.utils ...@@ -4,15 +4,15 @@ package net.mamoe.mirai.utils
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO import io.ktor.client.engine.cio.CIO
import kotlinx.io.core.IoBuffer import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.io.core.Output import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.io.core.copyTo import kotlinx.io.core.copyTo
import kotlinx.io.core.readBytes
import kotlinx.io.streams.asInput import kotlinx.io.streams.asInput
import kotlinx.io.streams.asOutput import kotlinx.io.streams.asOutput
import java.io.* import java.io.*
import java.net.InetAddress import java.net.InetAddress
import java.security.MessageDigest import java.security.MessageDigest
import java.util.concurrent.Executors
import java.util.zip.CRC32 import java.util.zip.CRC32
import java.util.zip.Inflater import java.util.zip.Inflater
...@@ -68,4 +68,8 @@ actual fun ByteArray.unzip(): ByteArray { ...@@ -68,4 +68,8 @@ actual fun ByteArray.unzip(): ByteArray {
} }
inflater.end() inflater.end()
return output.toByteArray() return output.toByteArray()
}
actual fun newCoroutineDispatcher(threadCount: Int): CoroutineDispatcher {
return Executors.newFixedThreadPool(threadCount).asCoroutineDispatcher()
} }
\ No newline at end of file
...@@ -2,15 +2,17 @@ ...@@ -2,15 +2,17 @@
package test package test
import kotlinx.serialization.* import kotlinx.serialization.ImplicitReflectionSerializer
import kotlinx.serialization.SerialId
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import kotlinx.serialization.protobuf.ProtoNumberType import kotlinx.serialization.protobuf.ProtoNumberType
import kotlinx.serialization.protobuf.ProtoType import kotlinx.serialization.protobuf.ProtoType
import kotlinx.serialization.serializer
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.readProtoMap import net.mamoe.mirai.utils.cryptor.readProtoMap
import net.mamoe.mirai.utils.io.hexToBytes import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.read import net.mamoe.mirai.utils.io.read
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.reflect.KClass import kotlin.reflect.KClass
@Serializable @Serializable
...@@ -25,15 +27,14 @@ data class ProtoTest( ...@@ -25,15 +27,14 @@ data class ProtoTest(
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
suspend fun main() { suspend fun main() {
println("PNG".toUtf8Bytes().toUHexString())
deserializeTest() deserializeTest()
} }
suspend fun deserializeTest() { suspend fun deserializeTest() {
val bytes = val bytes =
""" """
08 02 1A 55 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 1A 25 2F 34 35 35 38 66 39 30 38 2D 37 62 39 61 2D 34 65 32 66 2D 38 63 36 39 2D 34 61 35 32 61 66 62 33 36 35 61 37 20 01 30 04 38 05 40 09 48 01 58 00 60 01 6A 0A 38 2E 32 2E 30 2E 31 32 39 36 70 E0 8C B2 F0 05 78 01 50 03
""".trimIndent() """.trimIndent()
.replace("\n", " ") .replace("\n", " ")
.replace("UVarInt", "", ignoreCase = true) .replace("UVarInt", "", ignoreCase = true)
.replace("uint", "", ignoreCase = true) .replace("uint", "", ignoreCase = true)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment