mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-14 23:20:49 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
2e17ea6815
mirai-core-qqandroid/src
commonMain/kotlin/net/mamoe/mirai/qqandroid/network
QQAndroidBotNetworkHandler.kt
protocol/packet
jvmTest/kotlin/androidPacketTests
mirai-debug
@ -11,7 +11,6 @@ import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
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.RegPushReason
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
|
||||
import net.mamoe.mirai.utils.*
|
||||
@ -101,12 +100,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
*/
|
||||
suspend fun parsePacket(input: Input) {
|
||||
try {
|
||||
KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, packetId: PacketId, sequenceId: Int ->
|
||||
KnownPacketFactories.parseIncomingPacket(bot, input) { packet: Packet, commandName: String, sequenceId: Int ->
|
||||
if (PacketReceivedEvent(packet).broadcast().cancelled) {
|
||||
return@parseIncomingPacket
|
||||
}
|
||||
packetListeners.forEach { listener ->
|
||||
if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) {
|
||||
if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) {
|
||||
listener.complete(packet)
|
||||
}
|
||||
}
|
||||
@ -202,7 +201,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
|
||||
suspend fun <E : Packet> OutgoingPacket.sendAndExpect(): E {
|
||||
val handler = PacketListener(packetId = packetId, sequenceId = sequenceId)
|
||||
val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
|
||||
packetListeners.addLast(handler)
|
||||
//println(delegate.readBytes().toUHexString())
|
||||
println("Sending length=" + delegate.remaining)
|
||||
@ -217,10 +216,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
|
||||
@PublishedApi
|
||||
internal inner class PacketListener(
|
||||
val packetId: PacketId,
|
||||
val commandName: String,
|
||||
val sequenceId: Int
|
||||
) : CompletableDeferred<Packet> by CompletableDeferred(supervisor) {
|
||||
fun filter(packetId: PacketId, sequenceId: Int) = this.packetId == packetId && this.sequenceId == sequenceId
|
||||
fun filter(commandName: String, sequenceId: Int) = this.commandName == commandName && this.sequenceId == sequenceId
|
||||
}
|
||||
|
||||
override suspend fun awaitDisconnection() = supervisor.join()
|
||||
|
@ -6,8 +6,6 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
|
||||
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
|
||||
@ -23,12 +21,12 @@ import net.mamoe.mirai.utils.io.writeQQ
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
internal class OutgoingPacket constructor(
|
||||
name: String?,
|
||||
val packetId: PacketId,
|
||||
val commandName: String,
|
||||
val sequenceId: Int,
|
||||
val delegate: ByteReadPacket
|
||||
) {
|
||||
val name: String by lazy {
|
||||
name ?: packetId.toString()
|
||||
name ?: commandName.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,13 +64,13 @@ internal val EMPTY_BYTE_ARRAY = ByteArray(0)
|
||||
internal inline fun PacketFactory<*>.buildOutgingPacket(
|
||||
client: QQAndroidClient,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
commandName: String = this.commandName,
|
||||
key: ByteArray,
|
||||
body: BytePacketBuilder.(sequenceId: Int) -> Unit
|
||||
): OutgoingPacket {
|
||||
val sequenceId: Int = client.nextSsoSequenceId()
|
||||
|
||||
return OutgoingPacket(name, id, sequenceId, buildPacket {
|
||||
return OutgoingPacket(name, commandName, sequenceId, buildPacket {
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
writeInt(0x0B)
|
||||
writeByte(1)
|
||||
@ -113,13 +111,13 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
|
||||
bodyType: Byte,
|
||||
extraData: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
commandName: String = this.commandName,
|
||||
key: ByteArray = KEY_16_ZEROS,
|
||||
body: BytePacketBuilder.(sequenceId: Int) -> Unit
|
||||
): OutgoingPacket {
|
||||
val sequenceId: Int = client.nextSsoSequenceId()
|
||||
|
||||
return OutgoingPacket(name, id, sequenceId, buildPacket {
|
||||
return OutgoingPacket(name, commandName, sequenceId, buildPacket {
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
writeInt(0x00_00_00_0A)
|
||||
writeByte(bodyType)
|
||||
@ -168,10 +166,10 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
|
||||
* byte[] body()
|
||||
*/
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun BytePacketBuilder.writeLoginSsoPacket(
|
||||
internal inline fun BytePacketBuilder.writeSsoPacket(
|
||||
client: QQAndroidClient,
|
||||
subAppId: Long,
|
||||
packetId: PacketId,
|
||||
commandName: String,
|
||||
extraData: ByteReadPacket = BRP_STUB,
|
||||
sequenceId: Int,
|
||||
body: BytePacketBuilder.() -> Unit
|
||||
@ -187,7 +185,7 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
|
||||
writeInt((extraData.remaining + 4).toInt())
|
||||
writePacket(extraData)
|
||||
}
|
||||
packetId.commandName.let {
|
||||
commandName.let {
|
||||
writeInt(it.length + 4)
|
||||
writeStringUtf8(it)
|
||||
}
|
||||
@ -269,7 +267,7 @@ internal inline fun PacketFactory<*>.buildSessionOutgoingPacket(
|
||||
internal fun BytePacketBuilder.writeOicqRequestPacket(
|
||||
client: QQAndroidClient,
|
||||
encryptMethod: EncryptMethod,
|
||||
packetId: PacketId,
|
||||
commandId: Int,
|
||||
bodyBlock: BytePacketBuilder.() -> Unit
|
||||
) {
|
||||
val body = encryptMethod.makeBody(client, bodyBlock)
|
||||
@ -278,7 +276,7 @@ internal fun BytePacketBuilder.writeOicqRequestPacket(
|
||||
writeByte(0x02) // head
|
||||
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
|
||||
writeShort(client.protocolVersion)
|
||||
writeShort(packetId.commandId.toShort())
|
||||
writeShort(commandId.toShort())
|
||||
writeShort(1) // const??
|
||||
writeQQ(client.uin)
|
||||
writeByte(3) // originally const
|
||||
|
File diff suppressed because one or more lines are too long
@ -6,13 +6,12 @@ import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>() {
|
||||
init {
|
||||
this._id = PacketId(commandId = 0x0000, commandName = "LongConn.OffPicDown")
|
||||
this._commandName = "LongConn.OffPicDown"
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +20,7 @@ internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>()
|
||||
}
|
||||
|
||||
|
||||
fun createCmd0x325Packet(req: ImgReq, networkType: Int = 5): Cmd0x352Packet {
|
||||
private fun createCmd0x325Packet(req: ImgReq, networkType: Int = 5): Cmd0x352Packet {
|
||||
if (req is UploadImgReq)
|
||||
return Cmd0x352Packet(
|
||||
1,
|
||||
|
@ -25,7 +25,7 @@ import net.mamoe.mirai.utils.io.discardExact
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
|
||||
init {
|
||||
this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login")
|
||||
this._commandName = "wtlogin.login"
|
||||
}
|
||||
|
||||
object SubCommand9 {
|
||||
@ -36,8 +36,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
|
||||
operator fun invoke(
|
||||
client: QQAndroidClient
|
||||
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId ->
|
||||
writeLoginSsoPacket(client, subAppId, id, sequenceId = sequenceId) {
|
||||
writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), id) {
|
||||
writeSsoPacket(client, subAppId, commandName, sequenceId = sequenceId) {
|
||||
writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), 0x0810) {
|
||||
writeShort(9) // subCommand
|
||||
writeShort(17) // count of TLVs, probably ignored by server?
|
||||
//writeShort(LoginType.PASSWORD.value.toShort())
|
||||
@ -563,21 +563,4 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
|
||||
// SEE oicq_request.java at method analysisT17f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal fun PacketId(commandId: Int, commandName: String) = object : PacketId {
|
||||
override val commandId: Int get() = commandId
|
||||
override val commandName: String get() = commandName
|
||||
}
|
||||
|
||||
internal interface PacketId {
|
||||
val commandId: Int // ushort actually
|
||||
val commandName: String
|
||||
}
|
||||
|
||||
internal object NullPacketId : PacketId {
|
||||
override val commandId: Int get() = error("uninitialized")
|
||||
override val commandName: String get() = error("uninitialized")
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeLoginSsoPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
|
||||
import net.mamoe.mirai.qqandroid.utils.NetworkType
|
||||
import net.mamoe.mirai.utils.currentTimeSeconds
|
||||
import net.mamoe.mirai.utils.io.debugPrint
|
||||
@ -40,10 +40,10 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
|
||||
|
||||
internal object Response : Packet
|
||||
|
||||
const val subAppId = 537062845L
|
||||
private const val subAppId = 537062845L
|
||||
|
||||
init {
|
||||
_id = PacketId(0, "StatSvc.register")
|
||||
_commandName = "StatSvc.register"
|
||||
}
|
||||
|
||||
operator fun invoke(
|
||||
@ -55,8 +55,8 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
|
||||
extraData = client.wLoginSigInfo.d2.data,
|
||||
key = client.wLoginSigInfo.d2Key
|
||||
) { sequenceId ->
|
||||
writeLoginSsoPacket(
|
||||
client, subAppId = subAppId, packetId = id,
|
||||
writeSsoPacket(
|
||||
client, subAppId = subAppId, commandName = commandName,
|
||||
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
|
||||
) {
|
||||
writeUniRequestPacket {
|
||||
|
@ -10,7 +10,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
|
||||
|
||||
init {
|
||||
_id = PacketId(0x0812, "wtlogin.trans_emp")
|
||||
_commandName = "wtlogin.trans_emp"
|
||||
}
|
||||
|
||||
private const val appId = 16L
|
||||
@ -20,7 +20,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
|
||||
fun SubCommand1(
|
||||
client: QQAndroidClient
|
||||
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) {
|
||||
writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
|
||||
writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), TODO()) {
|
||||
|
||||
// oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody
|
||||
}
|
||||
|
@ -22,24 +22,24 @@ import kotlin.text.toByteArray
|
||||
// x2
|
||||
|
||||
// OidbSvc.0xcf8 (getShoppingCardInfo)send 20da22db750806141ef4481108004500009450fd400080060000c0a8030a71600dd0fe501f908b8c3b2908ce927e501801fe436900000000006c0000000b0100014e78000000000e31393934373031303231fde67e3ef90dfab4c8706743671f3abf660fc3f77e4efa3fabdeb96e9984107b3f4bf7677b5d34c72e88a6e212af9107e3c52c5f97b7e41c2c3cecfe9301293ab4be504d4d2eca28a816ec514deca805
|
||||
// OidbSvc.0x59f send 20da22db750806141ef4481108004500008c50fe400080060000c0a8030a71600dd0fe501f908b8c3b9508ce9366501801fe43610000000000640000000b0100014e7a000000000e313939343730313032319798479335a617d6037b4351bf340716d7095f01a83a19090ced9170a5d2e45578915b186770906f21b623304ee25b7ccb52126e3ab84275d2063f4801b3ea88f4b8fd064be98e75
|
||||
// OidbSvc.0x59f (requestIsFirstLogin) send 20da22db750806141ef4481108004500008c50fe400080060000c0a8030a71600dd0fe501f908b8c3b9508ce9366501801fe43610000000000640000000b0100014e7a000000000e313939343730313032319798479335a617d6037b4351bf340716d7095f01a83a19090ced9170a5d2e45578915b186770906f21b623304ee25b7ccb52126e3ab84275d2063f4801b3ea88f4b8fd064be98e75
|
||||
// friendlist.GetTroopListReqV2 send 20da22db750806141ef4481108004500011450ff400080060000c0a8030a71600dd0fe501f908b8c3bf908ce963e501801fb43e90000000000ec0000000b0100014e7b000000000e31393934373031303231e92012cde1f02af5088df9ee11e33f90ffc5416dce23cff1193985eb747ea1f453957b000b9f642708e394f590d5c8e7030064ef6f56210330319d4dd4fe21f0463095d74c6d5e21d94fcfb318c58e18d5a83ae548c03827b28c384e9a598f2ec9758ccb313fb825d44b727c10f8929682c5b6d34a8721f06e7ebb6768d39c6e1283b29bbdc15c6f35943fcc26195d1db57ae8de55d96637c7ae4caaa432bcf6768f17a39aa7f49882a86af04876146a2e44c3dcebf3ab106944cf7de19c85111add7b97c8d6bb53f773f11c09525614
|
||||
// OidbSvc.0x791_0 send 20da22db750806141ef448110800450000bc5101400080060000c0a8030a71600dd0fe501f908b8c3ce508ce96a6501801fa43910000000000940000000b0100014e7d000000000e313939343730313032311ca9030fef4676440544c30ee8455143b3d29bf4b96fcb3923e437c30fd64795a325c777e38cd08f173f5dd6814541ca160a2de1ebdb46dcd73386cbf35ee2faae6cdac5c91aa81cf0beca175d7fdee366bacea06859de8b3e163e95d6765256fc523b7e435dc8f73d1a3f5a5c6c793706c88e103a55efa5
|
||||
// OidbSvc.0x480_9 send 20da22db750806141ef4481108004500008c5102400080060000c0a8030a71600dd0fe501f908b8c3d7908ce97165018020043610000000000640000000b0100014e7e000000000e3139393437303130323183063dc1abd81bf314960d1a00d2a457ff44cb694c4d17d048b888600262a1a957713055cd6e2a68a55d239e1d70d26f9a39bfc61418a8cfbdd96dac2ae1be32e34f94a0271339d8
|
||||
// OidbSvc.0x5eb_15 send 20da22db750806141ef4481108004500009c5105400080060000c0a8030a71600dd0fe501f908b8c3ddd08ce9e7e501801fe43710000000000740000000b0100014e7f000000000e31393934373031303231e80e3bc84057f0f3cdbfcde52cf82c5c640f69afd3680638b3bbd86bab49ddb8e29e297815f1f41ddfecfe241f76b57f999b02988fe5bb6f92da0693e27e023baea0504b7ca768c541630e636c31a01bdce3df4c27f88906
|
||||
// OidbSvc.0x791_0 (getRedPointInfo) send 20da22db750806141ef448110800450000bc5101400080060000c0a8030a71600dd0fe501f908b8c3ce508ce96a6501801fa43910000000000940000000b0100014e7d000000000e313939343730313032311ca9030fef4676440544c30ee8455143b3d29bf4b96fcb3923e437c30fd64795a325c777e38cd08f173f5dd6814541ca160a2de1ebdb46dcd73386cbf35ee2faae6cdac5c91aa81cf0beca175d7fdee366bacea06859de8b3e163e95d6765256fc523b7e435dc8f73d1a3f5a5c6c793706c88e103a55efa5
|
||||
// OidbSvc.0x480_9 (getDetailCardInfo) send 20da22db750806141ef4481108004500008c5102400080060000c0a8030a71600dd0fe501f908b8c3d7908ce97165018020043610000000000640000000b0100014e7e000000000e3139393437303130323183063dc1abd81bf314960d1a00d2a457ff44cb694c4d17d048b888600262a1a957713055cd6e2a68a55d239e1d70d26f9a39bfc61418a8cfbdd96dac2ae1be32e34f94a0271339d8
|
||||
// OidbSvc.0x5eb_15 (getHiddenSwitch) send 20da22db750806141ef4481108004500009c5105400080060000c0a8030a71600dd0fe501f908b8c3ddd08ce9e7e501801fe43710000000000740000000b0100014e7f000000000e31393934373031303231e80e3bc84057f0f3cdbfcde52cf82c5c640f69afd3680638b3bbd86bab49ddb8e29e297815f1f41ddfecfe241f76b57f999b02988fe5bb6f92da0693e27e023baea0504b7ca768c541630e636c31a01bdce3df4c27f88906
|
||||
|
||||
// CliLogSvc.UploadReq send 20da22db750806141ef448110800450001cc5106400080060000c0a8030a71600dd0fe501f908b8c3e5108ce9eee501801fd44a10000000001a40000000b0100014e80000000000e31393934373031303231393e687d1ca6ee2f38f879c89a930bfbd7a9d0d5d6a84e3e76574b272980e8222c35564db3952d09f452bd954248922527ac9aee51a742b3508d50d3794ce81120245bff0a4e3ac74b026fb5444e9e5a5fad8a5c9865e855ede492fa445cc27e48a27f05d81f39e7f9818890717bffeab38df651f21e884cf5a7292c0f94aa3a849cbfdc84bc7e560e371fbbc4d62c1bd134b41f66915272cee5e4094ef47a5641cdb7e19a070a6babd955a02e722b2a5fbad6adc161f58f295d9a6406dd8bd9ac14bfc520e454eb2f0422ae20beaf6789d25ca367cb22fae28488670f5871e4fa7cd8953eb854a4b53cdd8ef0406f5efbd46870afb095efb7b375f956d4f085b6e03c7f7eada6b35d3cdc6e17c2e0169177f6bc24074f1a5fe90ea54cd8af627a00cb78518e6b7f3daab0811fc0872408581f385d25efeecfa4634998ffa81d43868521467262ff08f7fc338fac60499c3452f530bce46272599401fb4cf363ff74e8813c8e12a51b6bfb992e24d3dcf1dfde34af16e6e892f0a3cf146d2d3e444b62432e5e2932
|
||||
// CliLogSvc.UploadReq send 20da22db750806141ef448110800450001c45107400080060000c0a8030a71600dd0fe501f908b8c3ff508ce9eee501801fd449900000000019c0000000b0100014e81000000000e3139393437303130323128f6ceffe231f5a913fe9b4c59d24ea84d7dd8a67ef3c802f5eb2705ffeec4e98ddb95ec61e2adb2a52bcf4f744613a956a7af05be228b1dc95d40a0c4e187e79b495946e95bf2ffcabfc550c4f384269f87fea6d550a744a493cc0e11fea05cd7816fcf625b48ee6ed270e13fbacaeaef462a43dd17be5fa587e41e28fa40c083caa7e632cdcdef307404d75c30dce888de061ad715192916ec0b740c5614589b8e06683526042f8b74e896ba1049b71b8deff9354b1b2e83991d7426e2844cc592f511d9d51697361f6ef54370c4043b1bec4d7aa227804dc2b539ef95313b77561faa4d23f7392a2d18f5d796f7768af59d3faa65892169636d9c0e26a7b55be18bcb78719bd0a8ab5fa446f55e515ec5f2d0bfe9e0977ac98fe9af99f0426bc7d65066248d605eefed9b3c42f9d95d578e82515afce2fe239b857619bf64faadee7b10268bd3a079c23a413fffa209fdb9c7d23adab92e4c42fb446add76c24556d2f176f9020183814dfb2fa68861576bfcc41dfdd254d3a63dc8528b95
|
||||
// OidbSvc.0x787_11 send 20da22db750806141ef448110800450000a45108400080060000c0a8030a71600dd0fe501f908b8c419108ce9eee501801fd437900000000007c0000000b0100014e84000000000e31393934373031303231de7a3d7936e5679df9be661fdb98fa181243fed121a7c37e0a0a035537b27705ed59f5707bf86495d9b4781418f5c8dc36f561d8b659e2936d4549b55ec6c807650b4e5af7c79fe881ee9cb3df4b4b307748103b3b52eef06aeaf81adb25767c
|
||||
// OidbSvc.0xaf6_0 send 20da22db750806141ef44811080045000094510a400080060000c0a8030a71600dd0fe501f908b8c420d08ce9f86501801fd436900000000006c0000000b0100014e85000000000e313939343730313032311425f3e63a4e0a0454c45b48639abbe10c101b19f0a66f37e774289e87cc3c54def76486925c7291f5d37392120d7e0d30a9caba77f73808b201f49ff2a04a55c5ec502b10a6f861dbffb6eed7324b92
|
||||
// OidbSvc.0xdc9 send 20da22db750806141ef448110800450000d4510b400080060000c0a8030a71600dd0fe501f908b8c427908cea04e501801fc43a90000000000ac0000000b0100014e86000000000e31393934373031303231abc2f4d9170210b0504e058282363e45527ce2ec6080f48a99d24ca40171ab146ae451517cc60d98585c746d2d00d434d3b44a9e3c9bcbe0a5ee23d406d8ae9c88b9d51beae9d05a3c22fa67f5a03bea60c17017848d32852b7e6abbe290974f74183d7af2b20d6c43c133b52ec2506f9e752676a40518cf73b922505e1e5497fb58146e526627c8fdd2c8ec4424ff96
|
||||
// OidbSvc.0x787_11 (getTroopMemberListBy0x787) send 20da22db750806141ef448110800450000a45108400080060000c0a8030a71600dd0fe501f908b8c419108ce9eee501801fd437900000000007c0000000b0100014e84000000000e31393934373031303231de7a3d7936e5679df9be661fdb98fa181243fed121a7c37e0a0a035537b27705ed59f5707bf86495d9b4781418f5c8dc36f561d8b659e2936d4549b55ec6c807650b4e5af7c79fe881ee9cb3df4b4b307748103b3b52eef06aeaf81adb25767c
|
||||
// OidbSvc.0xaf6_0 (getTroopMemberListForHeadBatch) send 20da22db750806141ef44811080045000094510a400080060000c0a8030a71600dd0fe501f908b8c420d08ce9f86501801fd436900000000006c0000000b0100014e85000000000e313939343730313032311425f3e63a4e0a0454c45b48639abbe10c101b19f0a66f37e774289e87cc3c54def76486925c7291f5d37392120d7e0d30a9caba77f73808b201f49ff2a04a55c5ec502b10a6f861dbffb6eed7324b92
|
||||
// OidbSvc.0xdc9 (getHostTroopHonorList) send 20da22db750806141ef448110800450000d4510b400080060000c0a8030a71600dd0fe501f908b8c427908cea04e501801fc43a90000000000ac0000000b0100014e86000000000e31393934373031303231abc2f4d9170210b0504e058282363e45527ce2ec6080f48a99d24ca40171ab146ae451517cc60d98585c746d2d00d434d3b44a9e3c9bcbe0a5ee23d406d8ae9c88b9d51beae9d05a3c22fa67f5a03bea60c17017848d32852b7e6abbe290974f74183d7af2b20d6c43c133b52ec2506f9e752676a40518cf73b922505e1e5497fb58146e526627c8fdd2c8ec4424ff96
|
||||
// IncreaseURLSvr.QQHeadUrlReq, IncreaseURLSvr.QQHeadUrlReq send 20da22db750806141ef44811080045000150510c400080060000c0a8030a71600dd0fe501f908b8c432508cea116501801fb44250000000000b40000000b0100014e87000000000e31393934373031303231a3e5c904a29879bfe01d903db3522e51d9d388a6f976387267c78f937ebfb4b800cf847d9af9522bcf8b4e710d905935a904be7e144a8f85db87e784b42bdcc1f19b3dbf307b37d62ba3ee42e6145249161da0a9c608289f139e4f545b9efe40f868a9d7fc06381e59499b04da34e36aac978bb42ad6b93efa55fd63ddc18db1216c68afafc50c954caace2c159cc2ae5cdda25d4bcb5f2b000000740000000b0100014e88000000000e31393934373031303231c571c13b189ca8a129aeecfc734352ff401917c63da218afd73b3f95eaf5121a54331f4ae9534b5c5c5add7307c612fe935cbdfedb775ff1b386adba02b35984aac175015452125c1e93cb333e43c314d53cbb0201ebf0a5
|
||||
// OidbSvc.0xc42 send 20da22db750806141ef448110800450004ec510d400080060000c0a8030a71600dd0fe501f908b8c444d08cea3ee5018020047c10000000004c40000000b0100014e89000000000e31393934373031303231e59b7a31945585845fec9d893236808c4868e458601b681c89bdefb2b52d4c2b4f3f3d6e6abe0e0e0fc8df28dccc8733c80a4bb9869cfd7203664227c9c485d1e22d02f7fb24944d70542610a73cdb657fb915b1ded3c1a5a52eece81fddbe4df82302b948c88b51bb4fa1bcc9af6302304ffd89ae1fa47f6b732c84c1deb3d4b1bbd6818359f066be51e868d90bd500bb5b3d65ae0cc11a40c3aa03e3aa1e1144dea014d65d1d1ac82cbf6df2415c4b0629bd07323d61f5735bc768d0bbcc7be7fd66ebd9b65232b5491a7c2b33c1079f0af971c0ff178868361cd0fb40b05e3d421145e43a92696ef394f3fbc9e1ac0c037791aa57ad1c6542195c681eb951e7e59532fc9c1eed68c96e79e720d3057f1d6ae4cf4ef253af35fdb2feadec3bac82091d8146a7022b5f2578e3f126a474e9f1cec9d987b055c9217c003931a5cf03530a0062641e6f4549cedf50ea16c75feb7035a849a3229a3663c135cd8905f17176e878fe29942a55107895041595e5b497ca8796d9489d0682e8823589965240ade202ea0efa9f84f1ebc0e25d33e3e81b3a43d7bdc75005fe8b43d09fe914c6af785ba4ad4cb40cb41f5bc622af6dc1cad1460871b8c7fdec63e08a80536ddf340e907b1eddd8fa90d2323d3e2920c7cd80fd379d633e9f8b8c526f47f9e101d6a1edeccaf15d61c893cc55e9c192cd23b7a417c3175461096146a70a08717a8e654086d8db042b674e72dc54a057a80dd7dd291b85af7d4f7ee0b8dabb8a0e58cafb411f1e501b855a2e6ea6b5a089cb8d066d5d9181d0e16d5389123f96a06d630269efe3727ccc2ca84a4b3dbd1f5d786c3a655e2b3e9311bae60acf3855e55b5e96981295193564ab0172ab8fd6fb4a6c05bff477e7800dcfa6d1e6d2face51219e69987a1a03419ce7d6a43b6216f5f3f02d87b8c9e4faf227f4509427f3b26316f3e996a4a9dae90afc693b3eb359ecd2226087305d77bfe3f6fcbb949061f7a4d1076634144fa1b3f2491ca34d75ee4d3c7a4f4ba17233b7e56bcc8c04044ee5c0d0eed5c53814a6efc0347251e47eaf5981bfc5ccc7b3c2c9e6b2d8b5c1b81f2d79d5134420f5909d0526c5d761b94c0afade2dda634f2d44b911b977630dec1c3f7aa0ed1aea422aebb5c6aef49a9873ce5df751bea10926983c43843fa5adc56077f835e84bc07fd434867e4af0d605c64c729baa77e6a22d5b58d4b9378f518b10f57a61a486a815afb0e3591f85b5c5cdb37f5fba5c89b2638b21c27cc369acd6c995932ead6ceb49fdf6122e2c09b385eb43ffbf2e81acb31057beba0700fb388374ce9fb33794b3991e9b3a18123e732b8d14e5aef01391424200dab855c12b47ade4a2c60b760cd9e3c5400d452fa040ead996a21aad6ce6fac722121f35910b39a3cc8e20543fb2539fe3fe538162f086e1de508f0f9b0cc2414b8af6800ece710f944c95031d2536470ca87083a41641392edbf976413844cd7c7d64a6ed61a2f7ce8e09a6948099d62da1f81b28fcb50424f88b1f0a9b271a7172247ff0313e0dff87ef3b2b4d965852d200e0476fb56aba5a71e5e7a2ad500e62e7f15dc165f0a6b315bffde194822420b846fd18ed2f510eb2610d5d23ccaffbded2c495224c0a215859bf03f0cb1ffc7f3373aff418326c2a98c7a44e8bffe93b
|
||||
// ConfigPushSvc.GetIpDirect send 20da22db750806141ef44811080045000094510e400080060000c0a8030a71600dd0fe501f908b8c491108cea4b6501801ff436900000000006c0000000b0100014e8a000000000e31393934373031303231831dcd7b8023b2e8434f5897e7a34a13b67bcf4def875c650022a4a6b71417d9151938fe206612ae192f55d174e41aa848a02e51441700440260e2fdaf7882cfc60b2a10946dc2e76c172ddefc309389
|
||||
// * friendlist.getFriendGroupList send 20da22db750806141ef448110800450001245111400080060000c0a8030a71600dd0fe501f908b8c497d08ceae5e501801fd43f90000000000fc0000000b0100014ea4000000000e31393934373031303231899eb2e0bc999ad0799e23cd538fcb600850fda949fd86368e3897c1e1b736ce01509901fc190da6c2c0eb00edd851ebad2efac593997488b51ec58d289d3a050ff1a732a616e3b4fffd40b7aca1da2d04dc0c9e1205bcc63c9473d9ed5b4386cf41d4a786f7382f94266b09db3e3993a27bff4685ffb7d9eda7f66fcf592c8c8d593aa8c00e3fae4274371e5c4b4c3c23bdbc4f6a255d1f5b66f4bf2d56798099afbb34507f516d16ae24b344607bd23c899e241048c18b227a6094cbdcb12d2a8a33b443f7a4f26bc9b3f04fd8001daa46302bdeb22bf32bdc72d06c4a7959
|
||||
// * StatSvc.GetOnlineStatus send 20da22db750806141ef4481108004500008c5112400080060000c0a8030a71600dd0fe501f908b8c4a7908ceae5e501801fd43610000000000640000000b0100014ea5000000000e31393934373031303231954e34510d4f281e8676c7345c1e8d453c99aeca52c7649053a6230953ac2bca49f6e250394081be6153eceaa531aec179450ec3d671d72251db0c36cff7e1ba3b6de0e6ade53de2
|
||||
// * account.RequestQueryQQMobileContactsV3 send 20da22db750806141ef448110800450001445115400080060000c0a8030a71600dd0fe501f908b8c4add08ceba36501801ff441900000000011c0000000b0100014ea9000000000e31393934373031303231a78ed17a376177e537dec3ed98b7e47b51e9be299048820b1bf3ae88d8a18324e6773ef89922a7e7cd46f24d18a6f8aa53472bfeb09000bb7c44ef5f646d8a8f9e0d04accb35183b0216bea7dee1ef8a51207f11a0681fbcfcd09364a21b16bd6974fef7d66c7eca43aea623c499f1c81fb995d11d5490e64f7929861b670e2f24dc975684ea3098f0b96aff986b4e0b6b09a45bf7f2e301fa58ba1b462e755685681c112c3d2ac369d785d56c25c12b1c66bf39396030b374400879c922a7c43d6d36cc40aa8482f079ef48355b9a2562669f5bce3d3ace4f014ce0454b158693f2727833d62d29bdc7884b165b93c57e60d443351e9fff7e093494f0c61918
|
||||
// OidbSvc.0x58a send 20da22db750806141ef448110800450000945116400080060000c0a8030a71600dd0fe501f908b8c4bf908cebb5e501801fe436900000000006c0000000b0100014eaa000000000e3139393437303130323178d1c8e8c5d15a4dca043edc70fa514b19b92706d26a84f2bdb1b3e478d5ef53748b8d6082dea9a74f1c9f0ab519406c1ef36fcc0502cf201f658ecac1cd1682a34bb1ff42ac64da5f35e3af7fabcc8c
|
||||
// OidbSvc.0x58a (getDiscuss) send 20da22db750806141ef448110800450000945116400080060000c0a8030a71600dd0fe501f908b8c4bf908cebb5e501801fe436900000000006c0000000b0100014eaa000000000e3139393437303130323178d1c8e8c5d15a4dca043edc70fa514b19b92706d26a84f2bdb1b3e478d5ef53748b8d6082dea9a74f1c9f0ab519406c1ef36fcc0502cf201f658ecac1cd1682a34bb1ff42ac64da5f35e3af7fabcc8c
|
||||
// OidbSvc.0x7c4_0, OidbSvc.0xbe8 send 20da22db750806141ef448110800450001085117400080060000c0a8030a71600dd0fe501f908b8c4c6508cebbe6501801fe43dd00000000006c0000000b0100014eab000000000e31393934373031303231a047827363fff4e4596299c74f6d847be9e8b5c2e4327bdaddffb8dd40e8df0eb76c54a6c7b7a56eddbae7136bb2b076386eb3b51091c46e756d1f9241678b656498da02276578cfb1ebfb6445513f51000000740000000b0100014eac000000000e31393934373031303231bd70b59f03df1144ae0ab45768257763ae622d5517bc20092fffaf4a5a3d55118ef6cd02907467c0eaa4a45309661277166f75e8ec4b75c0ec5fbf313e03b4a667ce26dfb0d148039a4d9ef8be7ad8cdf5e5a810edb60dd4
|
||||
// OidbSvc.0x58b_0, CertifiedAccountSvc.certified_account_read.GetFollowList send 20da22db750806141ef448110800450002f05118400080060000c0a8030a71600dd0fe501f908b8c4d4508cebcd6501801fd45c500000000009c0000000b0100014ead000000000e313939343730313032311c087c0ad4a44631d3e9eb9a6ebb4456a003db2e7eaa5e27ffd4c3ee592b8de7b89b9f6a56fc8260e57eef4f3b6616a5255ab830548dd50e9a99cf87011584f3811591c35fc95cadfc364bbeb0ed337063a518aca85fd17c30ab57408389f5c071ed2626ec47b1086478164d0ae0bd0f21222eb7d4b7a5601bc160f99a8f70330000022c0000000b0100014eae000000000e313939343730313032312dd572fad1b71384d3fdb16a1c57f3cbadac7e41ae6de9d13cc2827262e4c5a4bb95829233b72b5f9076b4652c1ffd1ebba874003bcf7e3be86cdc1034ac656efde24be90a49484209c954b78dec531b3d194cc92a297efef340d8273de90a63335bf543109e96a5aa958283161e7e78f50b74b49adb176472ac82fdad36adb68b38421deba0d1c1dcf24f8342bb8d39c1181545a675abb92a3e28431e60a02aaca6c2b4f5ea79c3f4431865444932c9af983f07dd39dd6d81e47f0f59e386e5320051472fe9235f3b98b8850a9335074173730103565ddf81fb57fedb200f328d9ba16d2e52ecf1cc590382087529678501b1ab6b5866afb25b70f0d03b0773f84691e6b94e6d03c3c47f1baa4e17552fafce1bcc90e336ae0d7fca76babcb035378ce191aee9315885197a39301f319857c33cd25a017f6a0480e16030b623547216bafe886f41014f65ae2e6cf3b4c58a4ce96b8f0967c4b0e0be6a9e669c25a06e6b412f115522522af613c6b8fee922d4f3f189d3c2696521afd63fdfc4103bd827a3eb4aba949a6e07424510af29c74e3de4faa1706bf128ac7f9f66306852da2390bb6cb8ed34c885b49d577e22b86222e95142b351dec31690804b98d98baa66b405cb6d649069d9e21254f2f81a6963962955c86e6a74be6c159eb9dce9eff7eb7e0c34f864d826ececbc1e577b4498b403140983fd716ca2b04aa5c23b8c18fe28367bc5ba76081c4aafd3
|
||||
// CertifiedAccountSvc.certified_account_read.GetFollowList send 20da22db750806141ef44811080045000274511c400080060000c0a8030a71600dd0fe501f908b8c500d08ceca66501801ff454900000000024c0000000b0100014eaf000000000e313939343730313032318b6198dc33ae901346ecbe82c9821a5e2e7e68d070b2baa3dc8525246a625cb7461bf329a93acc9d20b0221108cd838505d2c0e2c9b944cf7c57eb17b74e74c99c873febfc6e89395b139c033c68d66b731b0ad4d9d7444471b7638628924c3ebb4c2ed326a87b1761d5d5a72043c5e3e538d5797843333867177b5f52445e0b5fa5805cba497e5f0f7da203da3504d74977180e1b86dcdb0c3b7298c4b10d6e53a145c277033e20445a82d0fcc78a1ce597294bf767e43ca42608e7531577d185cc14f91db8f3b71b614f5299ab75c448dd7462a0ce66b1a0992db05ebbab6667ca79ff39d2e9e5f58f73eb2b47cf1896e5560ebe389289b2222687ea8af254b4518ccc6d3468dd03ebce6247e7aac4278ba99210b4c91c49c6f29fd3ecb2653eae174e7bddaf40ef743f8da7605d09d36bca5ef84ee9b75d126db616fbe2b67cdbbb26809d56e97b2e4f6175da52694f0ee640ea1990dc79e5a0c2b266ddc16d0b7bf19818ad7727add2fd2ab379ba1b41763d953d0e21dd26e2f469e8273059f5130355a0976d5a01ca438f3b698b96a2c5394b6ebe381b3818b032ee5226a1a246935a741d39fb84feb917f9680d6c7b2e950e74def6523c318cbbe592904167f2ff8dbaf10616fb2b39a5af68fa19443e874ad2a6bc0639240903fccf8d2eecaacb9404c15ec387faf459f438c229e4a571234403078d270499a2634b13baf5051979ebe31ec8fedb55854e73d58534e51a924c637ee797389de4a27da494dbe7b50c69e1c4857537d3f369752e
|
||||
@ -49,29 +49,27 @@ import kotlin.text.toByteArray
|
||||
// ConfigPushSvc.PushResp, ** StatSvc.register send 20da22db750806141ef448110800450002f85124400080060000c0a8030a71600dd0fe501f908b8c558508cee2605018020045cd0000000000ac0000000b01a4da6eb0000000000e3139393437303130323122465f76192ce454d64e90a36fe651eb96d052893396c002a815851dc04994d16f7a596b06ca02b4743077fb387442f00409806ece8bf2f533a129073db60c8d5a22b9d4224387629e8ce29959a683f505b741aa1a83068239f6df0f97a4e5499c1035092e7466b005307110460211aecd1f11c10cea0cc861007e08882accb0bbaec68cd9c9a83fd19bb5eebda016ff000002240000000a0100000044e0e22a59327abb9ce80cf63be86694210344fab2f2b065d7785a32cacfa4075cd509f49cb37a075ad0685cbd472344bfdef1ede611c0ad81129be9e2d7e476d2000000000e31393934373031303231f4cf6ac405adbbfab64c0905f9f1f4b3236e4b17c34bc8aaefd77b184f012c036978eea06bb7f9e6d443a9d71f6eaf8b08b3c49858269de0405d7acf5076fd3000357cdbced53142200fcd8f87dc2a047ecfdd0d374aa0bb1b5c97b35e59a7cc77f146c930d04be6b70a75be3d71704d1b95794cbc36ef0ffe96533d61521c7b4b676f6b067859c0760ae5689f146b3c1a19668b694a50aa1d561f2feb76b49d507dc530d49007ba08f84297b23290177539d0b2a3ceb0a2ef8a64b65494e574ed78857fc1c93911c7639dce6699d5fde605f432d4ab7dfd6cf8cc5451950b29d79f5e755f90faadf55dfcb3993d9b4fb9479f44e47c1a0702205da298327b0deb180e2976d07be7b6ac0302b128d792200a092e084ca6908fe0c13e142d50f42783009029b3d2da23bd1050a2cc56023f943ce3b164002fa31fdf9624a255455cc77b774223726f36cccb2603240ca528534ee1533eb66872b007ea20bb5e76f87efa35d7dcb4be7e5f410ed7276c09e20f04db63ea4b79fd7d2201ef0ec14b5f9795bd2bd028e58b3ab8d3461a188f113a8b50406e9c3db9f8b2115924faadc9f2707c6715dc2dda73119228079467fbe145cf951cf1948e755aa428f4e478a6ab9708ad39ded4
|
||||
|
||||
|
||||
private val wtSessionTicketKey = "B6 9D E4 EC 65 38 64 FD C8 3A D8 33 54 35 0C 73".hexToBytes()
|
||||
private val tgtgtKey = "D7 71 03 E3 4C E5 8F 6B 05 D8 C7 8C 96 FB FB 23".hexToBytes()
|
||||
private val deviceToken = "CE 1E 2E DC 69 24 4F 9B FF 2F 52 D8 8F 69 DD 40".hexToBytes()
|
||||
private val D2Key = "44 28 6B 35 7A 54 2D 45 45 5D 56 32 44 33 47 49".hexToBytes()
|
||||
private val userStKey = "35 29 42 54 78 62 47 68 5E 77 68 54 6B 76 57 5F".hexToBytes()
|
||||
private val userStWebSig =
|
||||
internal val wtSessionTicketKey = "B6 9D E4 EC 65 38 64 FD C8 3A D8 33 54 35 0C 73".hexToBytes()
|
||||
internal val tgtgtKey = "D7 71 03 E3 4C E5 8F 6B 05 D8 C7 8C 96 FB FB 23".hexToBytes()
|
||||
internal val deviceToken = "CE 1E 2E DC 69 24 4F 9B FF 2F 52 D8 8F 69 DD 40".hexToBytes()
|
||||
internal val D2Key = "44 28 6B 35 7A 54 2D 45 45 5D 56 32 44 33 47 49".hexToBytes()
|
||||
internal val userStKey = "35 29 42 54 78 62 47 68 5E 77 68 54 6B 76 57 5F".hexToBytes()
|
||||
internal val userStWebSig =
|
||||
"63 A2 BD 78 FC 88 58 AC 12 95 6C 15 6A 9B A1 EB B0 E8 66 D0 95 D2 0E B4 BC C3 48 05 C1 D9 54 FB 65 8F 21 29 E5 5D 84 BA A1 63 48 5C 24 F3 84 A3".hexToBytes()
|
||||
private val tgtKey = "44 24 3F 43 3F 21 37 2B 29 44 6E 47 70 3A 4E 3D".hexToBytes()
|
||||
internal val tgtKey = "44 24 3F 43 3F 21 37 2B 29 44 6E 47 70 3A 4E 3D".hexToBytes()
|
||||
|
||||
private val t108 = "BD 12 96 6C 83 53 EF DD 06 16 52 16 B8 1B 25 69".hexToBytes()
|
||||
private val t10c = "23 7D 2C 7A 3F 4A 41 35 7D 3B 45 51 6D 3D 2A 56".hexToBytes()
|
||||
private val t163 = "2C 7A 7B 23 4E 24 3F 24 24 47 62 6B 69 2E 47 50".hexToBytes()
|
||||
internal val t108 = "BD 12 96 6C 83 53 EF DD 06 16 52 16 B8 1B 25 69".hexToBytes()
|
||||
internal val t10c = "23 7D 2C 7A 3F 4A 41 35 7D 3B 45 51 6D 3D 2A 56".hexToBytes()
|
||||
internal val t163 = "2C 7A 7B 23 4E 24 3F 24 24 47 62 6B 69 2E 47 50".hexToBytes()
|
||||
|
||||
private val shareKeyCalculatedByConstPubKey = ECDH.calculateShareKey(
|
||||
internal val shareKeyCalculatedByConstPubKey = ECDH.calculateShareKey(
|
||||
loadPrivateKey("97a52992cb7a2110413629af94a3c249c68a3b731510caa8"),
|
||||
initialPublicKey
|
||||
)
|
||||
|
||||
fun main() {
|
||||
|
||||
|
||||
val data = """
|
||||
20da22db750806141ef448110800450000d4512f400080060000c0a8030a71600dd0fe501f908b8c5c9908cf2416501801ff43a90000000000ac0000000b0100014f0d000000000e3139393437303130323193c94c8ce2871f6d5f6664df9e9231dedce5c7cb914cf5d616cf64af478aea9f210098e7f5efae9a952742b8fff704681885e5cc14a44e40d88910258f4a4a5cfcadd642cc159fdc475478475b18ba225cfad1c8bc2c5c828a9cc3ebaed1aa040d04b94f577fcfdb0861fd19754622733a242c5bcb37ca8597a2935d9910162111e44839b6787bb9be80058ad9c921c2
|
||||
20da22db750806141ef448110800450002f85124400080060000c0a8030a71600dd0fe501f908b8c558508cee2605018020045cd0000000000ac0000000b01a4da6eb0000000000e3139393437303130323122465f76192ce454d64e90a36fe651eb96d052893396c002a815851dc04994d16f7a596b06ca02b4743077fb387442f00409806ece8bf2f533a129073db60c8d5a22b9d4224387629e8ce29959a683f505b741aa1a83068239f6df0f97a4e5499c1035092e7466b005307110460211aecd1f11c10cea0cc861007e08882accb0bbaec68cd9c9a83fd19bb5eebda016ff000002240000000a0100000044e0e22a59327abb9ce80cf63be86694210344fab2f2b065d7785a32cacfa4075cd509f49cb37a075ad0685cbd472344bfdef1ede611c0ad81129be9e2d7e476d2000000000e31393934373031303231f4cf6ac405adbbfab64c0905f9f1f4b3236e4b17c34bc8aaefd77b184f012c036978eea06bb7f9e6d443a9d71f6eaf8b08b3c49858269de0405d7acf5076fd3000357cdbced53142200fcd8f87dc2a047ecfdd0d374aa0bb1b5c97b35e59a7cc77f146c930d04be6b70a75be3d71704d1b95794cbc36ef0ffe96533d61521c7b4b676f6b067859c0760ae5689f146b3c1a19668b694a50aa1d561f2feb76b49d507dc530d49007ba08f84297b23290177539d0b2a3ceb0a2ef8a64b65494e574ed78857fc1c93911c7639dce6699d5fde605f432d4ab7dfd6cf8cc5451950b29d79f5e755f90faadf55dfcb3993d9b4fb9479f44e47c1a0702205da298327b0deb180e2976d07be7b6ac0302b128d792200a092e084ca6908fe0c13e142d50f42783009029b3d2da23bd1050a2cc56023f943ce3b164002fa31fdf9624a255455cc77b774223726f36cccb2603240ca528534ee1533eb66872b007ea20bb5e76f87efa35d7dcb4be7e5f410ed7276c09e20f04db63ea4b79fd7d2201ef0ec14b5f9795bd2bd028e58b3ab8d3461a188f113a8b50406e9c3db9f8b2115924faadc9f2707c6715dc2dda73119228079467fbe145cf951cf1948e755aa428f4e478a6ab9708ad39ded4
|
||||
|
||||
|
||||
""".trimIndent()
|
||||
@ -101,12 +99,11 @@ fun ByteReadPacket.analysisOneFullPacket() = debugIfFail("Failed", { buildPacket
|
||||
val flag1 = readInt()
|
||||
println("flag1=" + flag1.contentToString())
|
||||
val flag2 = readByte().toInt()
|
||||
println("flag2=$flag2")
|
||||
if (flag1 == 0x0B) {
|
||||
if (flag2 == 1) {
|
||||
println("flag2=$flag2")
|
||||
println("sequenceId = " + readInt().toUHexString())
|
||||
} else {
|
||||
println("flag2=$flag2")
|
||||
println("extra data=" + readBytes(readInt() - 4).toUHexString())
|
||||
}
|
||||
} else {
|
||||
@ -124,9 +121,9 @@ fun ByteReadPacket.analysisOneFullPacket() = debugIfFail("Failed", { buildPacket
|
||||
|
||||
println("// 解密 body")
|
||||
readRemainingBytes().tryDecrypt().toReadPacket().debugPrint("outer body decrypted").apply {
|
||||
when (flag2) {
|
||||
2 -> decodeSso()
|
||||
1 -> decodeUni()
|
||||
when (flag1) {
|
||||
0x0A -> decodeSso()
|
||||
0x0B -> decodeUni()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -139,7 +136,7 @@ fun ByteReadPacket.decodeUni() {
|
||||
// 00 00 00 5B 10 03 2C 3C 4C 56 23 51 51 53 65 72 76 69 63 65 2E 43 6F 6E 66 69 67 50 75 73 68 53 76 63 2E 4D 61 69 6E 53 65 72 76 61 6E 74 66 08 50 75 73 68 52 65 73 70 7D 00 00 1A 08 00 01 06 08 50 75 73 68 52 65 73 70 1D 00 00 09 0A 10 01 22 14 DA 6E B1 0B 8C 98 0C A8 0C
|
||||
println("// 尝试解 Uni")
|
||||
println("// head")
|
||||
readBytes(readInt() - 4).read {
|
||||
readBytes(readInt() - 4).debugPrint("head").toReadPacket().apply {
|
||||
val commandName = readString(readInt() - 4).also { println("commandName=$it") }
|
||||
println(" unknown4Bytes=" + readBytes(readInt() - 4).toUHexString())
|
||||
// 00 00 00 1A 43 6F 6E 66 69 67 50 75 73 68 53 76 63 2E 50 75 73 68 52 65 73 70
|
||||
|
@ -41,8 +41,11 @@ fun ktor(id: String, version: String) = "io.ktor:ktor-$id:$version"
|
||||
|
||||
dependencies {
|
||||
|
||||
runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // IDE bug
|
||||
runtimeOnly(files("../mirai-core-timpc/build/classes/kotlin/jvm/main")) // IDE bug
|
||||
implementation(project(":mirai-core-timpc"))
|
||||
runtimeOnly(files("../mirai-core-qqandroid/build/classes/kotlin/jvm/main")) // IDE bug
|
||||
implementation(project(":mirai-core-qqandroid"))
|
||||
// runtimeOnly(files("../mirai-core/build/classes/kotlin/jvm/main")) // classpath is not added correctly by IDE
|
||||
|
||||
implementation("org.bouncycastle:bcprov-jdk15on:1.64")
|
||||
@ -70,4 +73,9 @@ dependencies {
|
||||
implementation(ktor("client-core", ktorVersion))
|
||||
implementation(ktor("network", ktorVersion))
|
||||
|
||||
testImplementation(kotlin("test-annotations-common"))
|
||||
testImplementation(kotlin("test"))
|
||||
testImplementation(kotlin("test-junit"))
|
||||
testImplementation(kotlin("script-runtime"))
|
||||
|
||||
}
|
79
mirai-debug/src/test/java/jce/jce/HexUtil.java
Normal file
79
mirai-debug/src/test/java/jce/jce/HexUtil.java
Normal file
@ -0,0 +1,79 @@
|
||||
package jce.jce;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
public class HexUtil {
|
||||
private static final char[] digits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
public static final byte[] emptybytes = new byte[0];
|
||||
|
||||
public static String byte2HexStr(byte var0) {
|
||||
char var1 = digits[var0 & 15];
|
||||
var0 = (byte) (var0 >>> 4);
|
||||
return new String(new char[]{digits[var0 & 15], var1});
|
||||
}
|
||||
|
||||
public static String bytes2HexStr(byte[] var0) {
|
||||
if (var0 != null && var0.length != 0) {
|
||||
char[] var3 = new char[var0.length * 2];
|
||||
|
||||
for (int var1 = 0; var1 < var0.length; ++var1) {
|
||||
byte var2 = var0[var1];
|
||||
var3[var1 * 2 + 1] = digits[var2 & 15];
|
||||
var2 = (byte) (var2 >>> 4);
|
||||
var3[var1 * 2 + 0] = digits[var2 & 15];
|
||||
}
|
||||
|
||||
return new String(var3);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte char2Byte(char var0) {
|
||||
if (var0 >= '0' && var0 <= '9') {
|
||||
return (byte) (var0 - 48);
|
||||
} else if (var0 >= 'a' && var0 <= 'f') {
|
||||
return (byte) (var0 - 97 + 10);
|
||||
} else {
|
||||
return var0 >= 'A' && var0 <= 'F' ? (byte) (var0 - 65 + 10) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte hexStr2Byte(String var0) {
|
||||
byte var2 = 0;
|
||||
byte var1 = var2;
|
||||
if (var0 != null) {
|
||||
var1 = var2;
|
||||
if (var0.length() == 1) {
|
||||
var1 = char2Byte(var0.charAt(0));
|
||||
}
|
||||
}
|
||||
|
||||
return var1;
|
||||
}
|
||||
|
||||
public static byte[] hexStr2Bytes(String var0) {
|
||||
if (var0 != null && !var0.equals("")) {
|
||||
byte[] var4 = new byte[var0.length() / 2];
|
||||
|
||||
for (int var3 = 0; var3 < var4.length; ++var3) {
|
||||
char var1 = var0.charAt(var3 * 2);
|
||||
char var2 = var0.charAt(var3 * 2 + 1);
|
||||
var4[var3] = (byte) (char2Byte(var1) * 16 + char2Byte(var2));
|
||||
}
|
||||
|
||||
return var4;
|
||||
} else {
|
||||
return emptybytes;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] var0) {
|
||||
try {
|
||||
byte[] var2 = "Hello WebSocket World?".getBytes("gbk");
|
||||
System.out.println(bytes2HexStr(var2));
|
||||
} catch (UnsupportedEncodingException var1) {
|
||||
var1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package jce.jce;
|
||||
|
||||
public class JceDecodeException extends RuntimeException {
|
||||
public JceDecodeException(String var1) {
|
||||
super(var1);
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package jce.jce;
|
||||
|
||||
public class JceEncodeException extends RuntimeException {
|
||||
public JceEncodeException(String var1) {
|
||||
super(var1);
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package jce.jce;
|
||||
|
||||
public class JceInputStream$HeadData {
|
||||
public int tag;
|
||||
public byte type;
|
||||
|
||||
public void clear() {
|
||||
this.type = 0;
|
||||
this.tag = 0;
|
||||
}
|
||||
}
|
1008
mirai-debug/src/test/java/jce/jce/JceInputStream.java
Normal file
1008
mirai-debug/src/test/java/jce/jce/JceInputStream.java
Normal file
File diff suppressed because it is too large
Load Diff
430
mirai-debug/src/test/java/jce/jce/JceOutputStream.java
Normal file
430
mirai-debug/src/test/java/jce/jce/JceOutputStream.java
Normal file
@ -0,0 +1,430 @@
|
||||
package jce.jce;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class JceOutputStream {
|
||||
// $FF: renamed from: bs java.nio.ByteBuffer
|
||||
private ByteBuffer field_80728;
|
||||
private OnIllegalArgumentException exceptionHandler;
|
||||
protected String sServerEncoding;
|
||||
|
||||
public JceOutputStream() {
|
||||
this(128);
|
||||
}
|
||||
|
||||
public JceOutputStream(int var1) {
|
||||
this.sServerEncoding = "GBK";
|
||||
this.field_80728 = ByteBuffer.allocate(var1);
|
||||
}
|
||||
|
||||
public JceOutputStream(ByteBuffer var1) {
|
||||
this.sServerEncoding = "GBK";
|
||||
this.field_80728 = var1;
|
||||
}
|
||||
|
||||
public static void main(String[] var0) {
|
||||
JceOutputStream var2 = new JceOutputStream();
|
||||
var2.write(1311768467283714885L, 0);
|
||||
ByteBuffer var1 = var2.getByteBuffer();
|
||||
System.out.println(HexUtil.bytes2HexStr(var1.array()));
|
||||
System.out.println(Arrays.toString(var2.toByteArray()));
|
||||
}
|
||||
|
||||
private void writeArray(Object[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ByteBuffer getByteBuffer() {
|
||||
return this.field_80728;
|
||||
}
|
||||
|
||||
public OnIllegalArgumentException getExceptionHandler() {
|
||||
return this.exceptionHandler;
|
||||
}
|
||||
|
||||
public void reserve(int var1) {
|
||||
if (this.field_80728.remaining() < var1) {
|
||||
int var2 = (this.field_80728.capacity() + var1) * 2;
|
||||
|
||||
ByteBuffer var3;
|
||||
try {
|
||||
var3 = ByteBuffer.allocate(var2);
|
||||
var3.put(this.field_80728.array(), 0, this.field_80728.position());
|
||||
} catch (IllegalArgumentException var4) {
|
||||
if (this.exceptionHandler != null) {
|
||||
this.exceptionHandler.onException(var4, this.field_80728, var1, var2);
|
||||
}
|
||||
|
||||
throw var4;
|
||||
}
|
||||
|
||||
this.field_80728 = var3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setExceptionHandler(OnIllegalArgumentException var1) {
|
||||
this.exceptionHandler = var1;
|
||||
}
|
||||
|
||||
public int setServerEncoding(String var1) {
|
||||
this.sServerEncoding = var1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
byte[] var1 = new byte[this.field_80728.position()];
|
||||
System.arraycopy(this.field_80728.array(), 0, var1, 0, this.field_80728.position());
|
||||
return var1;
|
||||
}
|
||||
|
||||
public void write(byte var1, int var2) {
|
||||
this.reserve(3);
|
||||
if (var1 == 0) {
|
||||
this.writeHead((byte) 12, var2);
|
||||
} else {
|
||||
this.writeHead((byte) 0, var2);
|
||||
this.field_80728.put(var1);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(double var1, int var3) {
|
||||
this.reserve(10);
|
||||
this.writeHead((byte) 5, var3);
|
||||
this.field_80728.putDouble(var1);
|
||||
}
|
||||
|
||||
public void write(float var1, int var2) {
|
||||
this.reserve(6);
|
||||
this.writeHead((byte) 4, var2);
|
||||
this.field_80728.putFloat(var1);
|
||||
}
|
||||
|
||||
public void write(int var1, int var2) {
|
||||
this.reserve(6);
|
||||
if (var1 >= -32768 && var1 <= 32767) {
|
||||
this.write((short) var1, var2);
|
||||
} else {
|
||||
this.writeHead((byte) 2, var2);
|
||||
this.field_80728.putInt(var1);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(long var1, int id) {
|
||||
this.reserve(10);
|
||||
if (var1 >= -2147483648L && var1 <= 2147483647L) {
|
||||
this.write((int) var1, id);
|
||||
} else {
|
||||
this.writeHead((byte) 3, id);
|
||||
this.field_80728.putLong(var1);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(JceStruct var1, int var2) {
|
||||
this.reserve(2);
|
||||
this.writeHead((byte) 10, var2);
|
||||
var1.writeTo(this);
|
||||
this.reserve(2);
|
||||
this.writeHead((byte) 11, 0);
|
||||
}
|
||||
|
||||
public void write(Boolean var1, int var2) {
|
||||
this.write((boolean) var1, var2);
|
||||
}
|
||||
|
||||
public void write(Byte var1, int var2) {
|
||||
this.write((byte) var1, var2);
|
||||
}
|
||||
|
||||
public void write(Double var1, int var2) {
|
||||
this.write((double) var1, var2);
|
||||
}
|
||||
|
||||
public void write(Float var1, int var2) {
|
||||
this.write((float) var1, var2);
|
||||
}
|
||||
|
||||
public void write(Integer var1, int var2) {
|
||||
this.write((int) var1, var2);
|
||||
}
|
||||
|
||||
public void write(Long var1, int var2) {
|
||||
this.write((long) var1, var2);
|
||||
}
|
||||
|
||||
public void write(Object var1, int var2) {
|
||||
if (var1 instanceof Byte) {
|
||||
this.write((Byte) var1, var2);
|
||||
} else if (var1 instanceof Boolean) {
|
||||
this.write((Boolean) var1, var2);
|
||||
} else if (var1 instanceof Short) {
|
||||
this.write((Short) var1, var2);
|
||||
} else if (var1 instanceof Integer) {
|
||||
this.write((Integer) var1, var2);
|
||||
} else if (var1 instanceof Long) {
|
||||
this.write((Long) var1, var2);
|
||||
} else if (var1 instanceof Float) {
|
||||
this.write((Float) var1, var2);
|
||||
} else if (var1 instanceof Double) {
|
||||
this.write((Double) var1, var2);
|
||||
} else if (var1 instanceof String) {
|
||||
this.write((String) var1, var2);
|
||||
} else if (var1 instanceof Map) {
|
||||
this.write((Map) var1, var2);
|
||||
} else if (var1 instanceof List) {
|
||||
this.write((List) var1, var2);
|
||||
} else if (var1 instanceof JceStruct) {
|
||||
this.write((JceStruct) var1, var2);
|
||||
} else if (var1 instanceof byte[]) {
|
||||
this.write((byte[]) var1, var2);
|
||||
} else if (var1 instanceof boolean[]) {
|
||||
this.write((boolean[]) var1, var2);
|
||||
} else if (var1 instanceof short[]) {
|
||||
this.write((short[]) var1, var2);
|
||||
} else if (var1 instanceof int[]) {
|
||||
this.write((int[]) var1, var2);
|
||||
} else if (var1 instanceof long[]) {
|
||||
this.write((long[]) var1, var2);
|
||||
} else if (var1 instanceof float[]) {
|
||||
this.write((float[]) var1, var2);
|
||||
} else if (var1 instanceof double[]) {
|
||||
this.write((double[]) var1, var2);
|
||||
} else if (var1.getClass().isArray()) {
|
||||
this.writeArray((Object[]) var1, var2);
|
||||
} else if (var1 instanceof Collection) {
|
||||
this.write((Collection) var1, var2);
|
||||
} else {
|
||||
throw new JceEncodeException("write object error: unsupport type. " + var1.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
public void write(Short var1, int var2) {
|
||||
this.write((short) var1, var2);
|
||||
}
|
||||
|
||||
public void write(String var1, int var2) {
|
||||
byte[] var5;
|
||||
label16:
|
||||
{
|
||||
byte[] var3;
|
||||
try {
|
||||
var3 = var1.getBytes(this.sServerEncoding);
|
||||
} catch (UnsupportedEncodingException var4) {
|
||||
var5 = var1.getBytes();
|
||||
break label16;
|
||||
}
|
||||
|
||||
var5 = var3;
|
||||
}
|
||||
|
||||
this.reserve(var5.length + 10);
|
||||
if (var5.length > 255) {
|
||||
this.writeHead((byte) 7, var2);
|
||||
this.field_80728.putInt(var5.length);
|
||||
} else {
|
||||
this.writeHead((byte) 6, var2);
|
||||
this.field_80728.put((byte) var5.length);
|
||||
}
|
||||
this.field_80728.put(var5);
|
||||
}
|
||||
|
||||
public <T> void write(Collection<T> var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
if (var1 == null) {
|
||||
var2 = 0;
|
||||
} else {
|
||||
var2 = var1.size();
|
||||
}
|
||||
|
||||
this.write(var2, 0);
|
||||
if (var1 != null) {
|
||||
|
||||
for (T t : var1) {
|
||||
this.write(t, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public <K, V> void write(Map<K, V> var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 8, var2);
|
||||
if (var1 == null) {
|
||||
var2 = 0;
|
||||
} else {
|
||||
var2 = var1.size();
|
||||
}
|
||||
|
||||
this.write(var2, 0);
|
||||
if (var1 != null) {
|
||||
|
||||
for (Entry<K, V> kvEntry : var1.entrySet()) {
|
||||
this.write(((Entry) kvEntry).getKey(), 0);
|
||||
this.write(((Entry) kvEntry).getValue(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void write(short var1, int var2) {
|
||||
this.reserve(4);
|
||||
if (var1 >= -128 && var1 <= 127) {
|
||||
this.write((byte) var1, var2);
|
||||
} else {
|
||||
this.writeHead((byte) 1, var2);
|
||||
this.field_80728.putShort(var1);
|
||||
}
|
||||
}
|
||||
|
||||
public void write(boolean var1, int var2) {
|
||||
byte var3;
|
||||
if (var1) {
|
||||
var3 = 1;
|
||||
} else {
|
||||
var3 = 0;
|
||||
}
|
||||
|
||||
this.write(var3, var2);
|
||||
}
|
||||
|
||||
public void write(byte[] var1, int var2) {
|
||||
this.reserve(var1.length + 8);
|
||||
this.writeHead((byte) 13, var2);
|
||||
this.writeHead((byte) 0, 0);
|
||||
this.write(var1.length, 0);
|
||||
this.field_80728.put(var1);
|
||||
}
|
||||
|
||||
public void write(double[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void write(float[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void write(int[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void write(long[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public <T> void write(T[] var1, int var2) {
|
||||
this.writeArray(var1, var2);
|
||||
}
|
||||
|
||||
public void write(short[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void write(boolean[] var1, int var2) {
|
||||
this.reserve(8);
|
||||
this.writeHead((byte) 9, var2);
|
||||
this.write(var1.length, 0);
|
||||
int var3 = var1.length;
|
||||
|
||||
for (var2 = 0; var2 < var3; ++var2) {
|
||||
this.write(var1[var2], 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void writeByteString(String var1, int var2) {
|
||||
this.reserve(var1.length() + 10);
|
||||
byte[] var3 = HexUtil.hexStr2Bytes(var1);
|
||||
if (var3.length > 255) {
|
||||
this.writeHead((byte) 7, var2);
|
||||
this.field_80728.putInt(var3.length);
|
||||
this.field_80728.put(var3);
|
||||
} else {
|
||||
this.writeHead((byte) 6, var2);
|
||||
this.field_80728.put((byte) var3.length);
|
||||
this.field_80728.put(var3);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeHead(byte var1, int var2) {
|
||||
byte var3;
|
||||
if (var2 < 15) {
|
||||
var3 = (byte) (var2 << 4 | var1);
|
||||
this.field_80728.put(var3);
|
||||
} else if (var2 < 256) {
|
||||
var3 = (byte) (var1 | 240);
|
||||
this.field_80728.put(var3);
|
||||
this.field_80728.put((byte) var2);
|
||||
} else {
|
||||
throw new JceEncodeException("tag is too large: " + var2);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeStringByte(String var1, int var2) {
|
||||
byte[] var3 = HexUtil.hexStr2Bytes(var1);
|
||||
this.reserve(var3.length + 10);
|
||||
if (var3.length > 255) {
|
||||
this.writeHead((byte) 7, var2);
|
||||
this.field_80728.putInt(var3.length);
|
||||
this.field_80728.put(var3);
|
||||
} else {
|
||||
this.writeHead((byte) 6, var2);
|
||||
this.field_80728.put((byte) var3.length);
|
||||
this.field_80728.put(var3);
|
||||
}
|
||||
}
|
||||
}
|
78
mirai-debug/src/test/java/jce/jce/JceStruct.java
Normal file
78
mirai-debug/src/test/java/jce/jce/JceStruct.java
Normal file
@ -0,0 +1,78 @@
|
||||
package jce.jce;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public abstract class JceStruct implements Serializable {
|
||||
public static final byte BYTE = 0;
|
||||
public static final byte DOUBLE = 5;
|
||||
public static final byte FLOAT = 4;
|
||||
public static final byte INT = 2;
|
||||
public static final int JCE_MAX_STRING_LENGTH = 104857600;
|
||||
public static final byte LIST = 9;
|
||||
public static final byte LONG = 3;
|
||||
public static final byte MAP = 8;
|
||||
public static final byte SHORT = 1;
|
||||
public static final byte SIMPLE_LIST = 13;
|
||||
public static final byte STRING1 = 6;
|
||||
public static final byte STRING4 = 7;
|
||||
public static final byte STRUCT_BEGIN = 10;
|
||||
public static final byte STRUCT_END = 11;
|
||||
public static final byte ZERO_TAG = 12;
|
||||
|
||||
public static String toDisplaySimpleString(JceStruct var0) {
|
||||
if (var0 == null) {
|
||||
return null;
|
||||
} else {
|
||||
StringBuilder var1 = new StringBuilder();
|
||||
var0.displaySimple(var1, 0);
|
||||
return var1.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containField(String var1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void display(StringBuilder var1, int var2) {
|
||||
}
|
||||
|
||||
public void displaySimple(StringBuilder var1, int var2) {
|
||||
}
|
||||
|
||||
public Object getFieldByName(String var1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JceStruct newInit() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void readFrom(JceInputStream var1);
|
||||
|
||||
public void recyle() {
|
||||
}
|
||||
|
||||
public void setFieldByName(String var1, Object var2) {
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
JceOutputStream var1 = new JceOutputStream();
|
||||
this.writeTo(var1);
|
||||
return var1.toByteArray();
|
||||
}
|
||||
|
||||
public byte[] toByteArray(String var1) {
|
||||
JceOutputStream var2 = new JceOutputStream();
|
||||
var2.setServerEncoding(var1);
|
||||
this.writeTo(var2);
|
||||
return var2.toByteArray();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder var1 = new StringBuilder();
|
||||
this.display(var1, 0);
|
||||
return var1.toString();
|
||||
}
|
||||
|
||||
public abstract void writeTo(JceOutputStream var1);
|
||||
}
|
594
mirai-debug/src/test/java/jce/jce/JceUtil.java
Normal file
594
mirai-debug/src/test/java/jce/jce/JceUtil.java
Normal file
@ -0,0 +1,594 @@
|
||||
package jce.jce;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public final class JceUtil {
|
||||
private static final byte[] highDigits;
|
||||
private static final int iConstant = 37;
|
||||
private static final int iTotal = 17;
|
||||
private static final byte[] lowDigits;
|
||||
|
||||
static {
|
||||
byte[] var1 = new byte[]{48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70};
|
||||
byte[] var2 = new byte[256];
|
||||
byte[] var3 = new byte[256];
|
||||
|
||||
for (int var0 = 0; var0 < 256; ++var0) {
|
||||
var2[var0] = var1[var0 >>> 4];
|
||||
var3[var0] = var1[var0 & 15];
|
||||
}
|
||||
|
||||
highDigits = var2;
|
||||
lowDigits = var3;
|
||||
}
|
||||
|
||||
public static int compareTo(byte var0, byte var1) {
|
||||
if (var0 < var1) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var1 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareTo(char var0, char var1) {
|
||||
if (var0 < var1) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var1 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareTo(double var0, double var2) {
|
||||
if (var0 < var2) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var2 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareTo(float var0, float var1) {
|
||||
if (var0 < var1) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var1 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareTo(int var0, int var1) {
|
||||
if (var0 < var1) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var1 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareTo(long var0, long var2) {
|
||||
if (var0 < var2) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var2 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compareTo(T var0, T var1) {
|
||||
return var0.compareTo(var1);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compareTo(List<T> var0, List<T> var1) {
|
||||
Iterator var3 = var0.iterator();
|
||||
Iterator var4 = var1.iterator();
|
||||
|
||||
while (var3.hasNext() && var4.hasNext()) {
|
||||
int var2 = ((Comparable) var3.next()).compareTo(var4.next());
|
||||
if (var2 != 0) {
|
||||
return var2;
|
||||
}
|
||||
}
|
||||
|
||||
return compareTo(var3.hasNext(), var4.hasNext());
|
||||
}
|
||||
|
||||
public static int compareTo(short var0, short var1) {
|
||||
if (var0 < var1) {
|
||||
return -1;
|
||||
} else {
|
||||
return var0 > var1 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static int compareTo(boolean var0, boolean var1) {
|
||||
byte var3 = 1;
|
||||
byte var2;
|
||||
if (var0) {
|
||||
var2 = 1;
|
||||
} else {
|
||||
var2 = 0;
|
||||
}
|
||||
|
||||
if (!var1) {
|
||||
var3 = 0;
|
||||
}
|
||||
|
||||
return var2 - var3;
|
||||
}
|
||||
|
||||
public static int compareTo(byte[] var0, byte[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(char[] var0, char[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(double[] var0, double[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(float[] var0, float[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(int[] var0, int[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(long[] var0, long[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static <T extends Comparable<T>> int compareTo(T[] var0, T[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = var0[var2].compareTo(var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(short[] var0, short[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static int compareTo(boolean[] var0, boolean[] var1) {
|
||||
int var3 = 0;
|
||||
|
||||
for (int var2 = 0; var2 < var0.length && var3 < var1.length; ++var2) {
|
||||
int var4 = compareTo(var0[var2], var1[var3]);
|
||||
if (var4 != 0) {
|
||||
return var4;
|
||||
}
|
||||
|
||||
++var3;
|
||||
}
|
||||
|
||||
return compareTo(var0.length, var1.length);
|
||||
}
|
||||
|
||||
public static boolean equals(byte var0, byte var1) {
|
||||
return var0 == var1;
|
||||
}
|
||||
|
||||
public static boolean equals(char var0, char var1) {
|
||||
return var0 == var1;
|
||||
}
|
||||
|
||||
public static boolean equals(double var0, double var2) {
|
||||
return var0 == var2;
|
||||
}
|
||||
|
||||
public static boolean equals(float var0, float var1) {
|
||||
return var0 == var1;
|
||||
}
|
||||
|
||||
public static boolean equals(int var0, int var1) {
|
||||
return var0 == var1;
|
||||
}
|
||||
|
||||
public static boolean equals(long var0, long var2) {
|
||||
return var0 == var2;
|
||||
}
|
||||
|
||||
public static boolean equals(Object var0, Object var1) {
|
||||
return var0.equals(var1);
|
||||
}
|
||||
|
||||
public static boolean equals(short var0, short var1) {
|
||||
return var0 == var1;
|
||||
}
|
||||
|
||||
public static boolean equals(boolean var0, boolean var1) {
|
||||
return var0 == var1;
|
||||
}
|
||||
|
||||
public static String getHexdump(ByteBuffer var0) {
|
||||
int var1 = var0.remaining();
|
||||
if (var1 == 0) {
|
||||
return "empty";
|
||||
} else {
|
||||
StringBuffer var4 = new StringBuffer(var0.remaining() * 3 - 1);
|
||||
int var2 = var0.position();
|
||||
int var3 = var0.get() & 255;
|
||||
var4.append((char) highDigits[var3]);
|
||||
var4.append((char) lowDigits[var3]);
|
||||
--var1;
|
||||
|
||||
while (var1 > 0) {
|
||||
var4.append(' ');
|
||||
var3 = var0.get() & 255;
|
||||
var4.append((char) highDigits[var3]);
|
||||
var4.append((char) lowDigits[var3]);
|
||||
--var1;
|
||||
}
|
||||
|
||||
var0.position(var2);
|
||||
return var4.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getHexdump(byte[] var0) {
|
||||
return getHexdump(ByteBuffer.wrap(var0));
|
||||
}
|
||||
|
||||
public static byte[] getJceBufArray(ByteBuffer var0) {
|
||||
byte[] var1 = new byte[var0.position()];
|
||||
System.arraycopy(var0.array(), 0, var1, 0, var1.length);
|
||||
return var1;
|
||||
}
|
||||
|
||||
public static int hashCode(byte var0) {
|
||||
return var0 + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(char var0) {
|
||||
return var0 + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(double var0) {
|
||||
return hashCode(Double.doubleToLongBits(var0));
|
||||
}
|
||||
|
||||
public static int hashCode(float var0) {
|
||||
return Float.floatToIntBits(var0) + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(int var0) {
|
||||
return var0 + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(long var0) {
|
||||
return (int) (var0 >> 32 ^ var0) + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(Object var0) {
|
||||
if (var0 == null) {
|
||||
return 629;
|
||||
} else if (var0.getClass().isArray()) {
|
||||
if (var0 instanceof long[]) {
|
||||
return hashCode((long[]) ((long[]) var0));
|
||||
} else if (var0 instanceof int[]) {
|
||||
return hashCode((int[]) ((int[]) var0));
|
||||
} else if (var0 instanceof short[]) {
|
||||
return hashCode((short[]) ((short[]) var0));
|
||||
} else if (var0 instanceof char[]) {
|
||||
return hashCode((char[]) ((char[]) var0));
|
||||
} else if (var0 instanceof byte[]) {
|
||||
return hashCode((byte[]) ((byte[]) var0));
|
||||
} else if (var0 instanceof double[]) {
|
||||
return hashCode((double[]) ((double[]) var0));
|
||||
} else if (var0 instanceof float[]) {
|
||||
return hashCode((float[]) ((float[]) var0));
|
||||
} else if (var0 instanceof boolean[]) {
|
||||
return hashCode((boolean[]) ((boolean[]) var0));
|
||||
} else {
|
||||
return var0 instanceof JceStruct[] ? hashCode((JceStruct[]) ((JceStruct[]) var0)) : hashCode((Object) ((Object[]) ((Object[]) var0)));
|
||||
}
|
||||
} else {
|
||||
return var0 instanceof JceStruct ? var0.hashCode() : var0.hashCode() + 629;
|
||||
}
|
||||
}
|
||||
|
||||
public static int hashCode(short var0) {
|
||||
return var0 + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(boolean var0) {
|
||||
byte var1;
|
||||
if (var0) {
|
||||
var1 = 0;
|
||||
} else {
|
||||
var1 = 1;
|
||||
}
|
||||
|
||||
return var1 + 629;
|
||||
}
|
||||
|
||||
public static int hashCode(byte[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + var0[var2];
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(char[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + var0[var2];
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(double[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + (int) (Double.doubleToLongBits(var0[var2]) ^ Double.doubleToLongBits(var0[var2]) >> 32);
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(float[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + Float.floatToIntBits(var0[var2]);
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(int[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + var0[var2];
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(long[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + (int) (var0[var2] ^ var0[var2] >> 32);
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(JceStruct[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + var0[var2].hashCode();
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(short[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
var1 = var1 * 37 + var0[var2];
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
|
||||
public static int hashCode(boolean[] var0) {
|
||||
int var3;
|
||||
if (var0 == null) {
|
||||
var3 = 629;
|
||||
} else {
|
||||
int var1 = 17;
|
||||
int var2 = 0;
|
||||
|
||||
while (true) {
|
||||
var3 = var1;
|
||||
if (var2 >= var0.length) {
|
||||
break;
|
||||
}
|
||||
|
||||
byte var4;
|
||||
if (var0[var2]) {
|
||||
var4 = 0;
|
||||
} else {
|
||||
var4 = 1;
|
||||
}
|
||||
|
||||
var1 = var4 + var1 * 37;
|
||||
++var2;
|
||||
}
|
||||
}
|
||||
|
||||
return var3;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package jce.jce;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public interface OnIllegalArgumentException {
|
||||
void onException(IllegalArgumentException var1, ByteBuffer var2, int var3, int var4);
|
||||
}
|
293
mirai-debug/src/test/kotlin/jceTest/jceTest.kt
Normal file
293
mirai-debug/src/test/kotlin/jceTest/jceTest.kt
Normal file
@ -0,0 +1,293 @@
|
||||
package jceTest
|
||||
|
||||
import io.ktor.util.InternalAPI
|
||||
import jce.jce.JceInputStream
|
||||
import jce.jce.JceOutputStream
|
||||
import jce.jce.JceStruct
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
import net.mamoe.mirai.qqandroid.network.io.JceInput
|
||||
import net.mamoe.mirai.qqandroid.network.io.JceOutput
|
||||
import net.mamoe.mirai.qqandroid.network.io.buildJcePacket
|
||||
import net.mamoe.mirai.utils.io.toUHexString
|
||||
import org.junit.Test
|
||||
|
||||
private infix fun ByteReadPacket.shouldEqualTo(another: ByteArray) {
|
||||
this.readBytes().let {
|
||||
check(it.contentEquals(another)) {
|
||||
"""actual: ${it.toUHexString()}
|
||||
|required: ${another.toUHexString()}
|
||||
""".trimMargin()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@UseExperimental(InternalAPI::class)
|
||||
private fun qqJce(block: JceOutputStream.() -> Unit): ByteArray {
|
||||
return JceOutputStream().apply(block).toByteArray()
|
||||
}
|
||||
|
||||
internal class JceOutputTest {
|
||||
|
||||
@Test
|
||||
fun writeByte() {
|
||||
buildJcePacket {
|
||||
writeByte(1, 1)
|
||||
writeByte(-128, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(1.toByte(), 1)
|
||||
write((-128).toByte(), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeDouble() {
|
||||
buildJcePacket {
|
||||
writeDouble(1.0, 1)
|
||||
writeDouble(-128.0, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(1.toDouble(), 1)
|
||||
write((-128).toDouble(), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeFloat() {
|
||||
buildJcePacket {
|
||||
writeFloat(1.0f, 1)
|
||||
writeFloat(-128.0f, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(1.toFloat(), 1)
|
||||
write((-128).toFloat(), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeFully() {
|
||||
buildJcePacket {
|
||||
writeFully(byteArrayOf(1, 2), 1)
|
||||
writeFully(byteArrayOf(1, 2), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(byteArrayOf(1, 2), 1)
|
||||
write(byteArrayOf(1, 2), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully() {
|
||||
buildJcePacket {
|
||||
writeFully(intArrayOf(1, 2), 1)
|
||||
writeFully(intArrayOf(1, 2), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(intArrayOf(1, 2), 1)
|
||||
write(intArrayOf(1, 2), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully1() {
|
||||
buildJcePacket {
|
||||
writeFully(shortArrayOf(1, 2), 1)
|
||||
writeFully(shortArrayOf(1, 2), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(shortArrayOf(1, 2), 1)
|
||||
write(shortArrayOf(1, 2), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully2() {
|
||||
buildJcePacket {
|
||||
writeFully(booleanArrayOf(true, false), 1)
|
||||
writeFully(booleanArrayOf(true, false), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(booleanArrayOf(true, false), 1)
|
||||
write(booleanArrayOf(true, false), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully3() {
|
||||
buildJcePacket {
|
||||
writeFully(longArrayOf(1, 2), 1)
|
||||
writeFully(longArrayOf(1, 2), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(longArrayOf(1, 2), 1)
|
||||
write(longArrayOf(1, 2), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully4() {
|
||||
buildJcePacket {
|
||||
writeFully(floatArrayOf(1f, 2f), 1)
|
||||
writeFully(floatArrayOf(1f, 2f), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(floatArrayOf(1f, 2f), 1)
|
||||
write(floatArrayOf(1f, 2f), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully5() {
|
||||
buildJcePacket {
|
||||
writeFully(doubleArrayOf(1.0, 2.0), 1)
|
||||
writeFully(doubleArrayOf(1.0, 2.0), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(doubleArrayOf(1.0, 2.0), 1)
|
||||
write(doubleArrayOf(1.0, 2.0), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWriteFully6() {
|
||||
buildJcePacket {
|
||||
writeFully(arrayOf("123", "哈哈"), 1)
|
||||
writeFully(arrayOf("123", "哈哈"), 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(arrayOf("123", "哈哈"), 1)
|
||||
write(arrayOf("123", "哈哈"), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeInt() {
|
||||
buildJcePacket {
|
||||
writeInt(1, 1)
|
||||
writeInt(-128, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(1, 1)
|
||||
write(-128, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeLong() {
|
||||
buildJcePacket {
|
||||
writeLong(1, 1)
|
||||
writeLong(-128, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(1L, 1)
|
||||
write(-128L, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeShort() {
|
||||
buildJcePacket {
|
||||
writeShort(1, 1)
|
||||
writeShort(-128, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(1.toShort(), 1)
|
||||
write((-128).toShort(), 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeBoolean() {
|
||||
buildJcePacket {
|
||||
writeBoolean(true, 1)
|
||||
writeBoolean(false, 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write(true, 1)
|
||||
write(false, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeString() {
|
||||
buildJcePacket {
|
||||
writeString("1", 1)
|
||||
writeString("哈啊", 2)
|
||||
} shouldEqualTo qqJce {
|
||||
write("1", 1)
|
||||
write("哈啊", 2)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeMap() {
|
||||
buildJcePacket {
|
||||
writeMap(mapOf("" to ""), 1)
|
||||
writeMap(mapOf("" to 123), 2)
|
||||
writeMap(mapOf(123.0 to "Hello"), 3)
|
||||
} shouldEqualTo qqJce {
|
||||
write(mapOf("" to ""), 1)
|
||||
write(mapOf("" to 123), 2)
|
||||
write(mapOf(123.0 to "Hello"), 3)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeCollection() {
|
||||
buildJcePacket {
|
||||
writeMap(mapOf("" to ""), 1)
|
||||
writeMap(mapOf("" to 123), 2)
|
||||
writeMap(mapOf(123.0 to "Hello"), 3)
|
||||
} shouldEqualTo qqJce {
|
||||
write(mapOf("" to ""), 1)
|
||||
write(mapOf("" to 123), 2)
|
||||
write(mapOf(123.0 to "Hello"), 3)
|
||||
}
|
||||
}
|
||||
|
||||
data class TestMiraiStruct(
|
||||
val message: String
|
||||
) : net.mamoe.mirai.qqandroid.network.io.JceStruct() {
|
||||
override fun writeTo(builder: JceOutput) {
|
||||
builder.writeString(message, 0)
|
||||
}
|
||||
|
||||
companion object : Factory<TestMiraiStruct> {
|
||||
override fun newInstanceFrom(input: JceInput): TestMiraiStruct {
|
||||
return TestMiraiStruct(input.readString(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestQQStruct(
|
||||
private var message: String
|
||||
) : JceStruct() {
|
||||
override fun readFrom(var1: JceInputStream) {
|
||||
message = var1.read("", 0, true)
|
||||
}
|
||||
|
||||
override fun writeTo(var1: JceOutputStream) {
|
||||
var1.write(message, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeJceStruct() {
|
||||
buildJcePacket {
|
||||
writeJceStruct(TestMiraiStruct("Hello"), 0)
|
||||
writeJceStruct(TestMiraiStruct("嗨"), 1)
|
||||
} shouldEqualTo qqJce {
|
||||
write(TestQQStruct("Hello"), 0)
|
||||
write(TestQQStruct("嗨"), 1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun writeObject() {
|
||||
buildJcePacket {
|
||||
writeObject(0.toByte(), 1)
|
||||
writeObject(0.toShort(), 2)
|
||||
writeObject(0, 3)
|
||||
writeObject(0L, 4)
|
||||
writeObject(0f, 5)
|
||||
writeObject(0.0, 6)
|
||||
writeObject("hello", 7)
|
||||
writeObject(TestMiraiStruct("Hello"), 8)
|
||||
} shouldEqualTo qqJce {
|
||||
write(0.toByte(), 1)
|
||||
write(0.toShort(), 2)
|
||||
write(0, 3)
|
||||
write(0L, 4)
|
||||
write(0f, 5)
|
||||
write(0.0, 6)
|
||||
write("hello", 7)
|
||||
write(TestQQStruct("Hello"), 8)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user