From 04c54f2a837d7a0fb81d6508211e9fc9fe4454bb Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 17 Jan 2020 22:35:24 +0800 Subject: [PATCH] Daily QQA Update --- .../mirai/qqandroid/utils/SystemDeviceInfo.kt | 1 + .../network/QQAndroidBotNetworkHandler.kt | 6 + .../qqandroid/network/QQAndroidClient.kt | 6 +- .../mirai/qqandroid/network/io/JceOutput.kt | 43 +++++- .../mirai/qqandroid/network/io/JceStruct.kt | 4 +- .../network/protocol/jce/RequestPacket.kt | 32 +++++ .../network/protocol/jce/SvcReqRegister.kt | 123 ++++++++++++++++++ .../qqandroid/network/protocol/jce/uni.kt | 12 ++ .../network/protocol/packet/MessageMicro.kt | 9 ++ .../protocol/packet/OutgoingPacketAndroid.kt | 33 +++-- .../network/protocol/packet/PacketFactory.kt | 12 +- .../protocol/packet/login/LoginPacket.kt | 17 ++- .../packet/login/SvcReqRegisterPacket.kt | 113 ++++++++++++++++ .../protocol/packet/login/TransEmpPacket.kt | 2 +- .../command/GetPublicAccountDetailInfo.kt | 19 +++ .../packet/oidb/oidb0x769/Oidb0x769.kt | 85 ++++++++++++ .../packet/oidb/sso/OidbSsoPackage.kt | 22 ++++ .../mamoe/mirai/qqandroid/utils/DeviceInfo.kt | 18 ++- .../mirai/qqandroid/utils/SystemDeviceInfo.kt | 1 + .../net.mamoe.mirai/utils/io/ByteArrayPool.kt | 2 +- .../net.mamoe.mirai/utils/io/ByteArrayUtil.kt | 4 +- 21 files changed, 530 insertions(+), 34 deletions(-) create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/MessageMicro.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/SvcReqRegisterPacket.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/command/GetPublicAccountDetailInfo.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/oidb0x769/Oidb0x769.kt create mode 100644 mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/sso/OidbSsoPackage.kt diff --git a/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt b/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt index 6de434566..2db2d14bc 100644 --- a/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt +++ b/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt @@ -84,5 +84,6 @@ actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo( override val incremental: ByteArray get() = Build.VERSION.INCREMENTAL.toByteArray() override val release: ByteArray get() = Build.VERSION.RELEASE.toByteArray() override val codename: ByteArray get() = Build.VERSION.CODENAME.toByteArray() + override val sdk: Int get() = Build.VERSION.SDK_INT } } \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index e5e1892d0..1d8f6d487 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -12,8 +12,11 @@ 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.LockFreeLinkedList import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.getValue import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.unsafeWeakRef import kotlin.coroutines.CoroutineContext @@ -33,7 +36,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler println("Sending login") LoginPacket.SubCommand9(bot.client).sendAndExpect() println("SessionTicket=${bot.client.wLoginSigInfo.wtSessionTicket.data.toUHexString()}") + println("SessionTicketKey=${bot.client.wLoginSigInfo.d2Key.toUHexString()}") println("SessionTicketKey=${bot.client.wLoginSigInfo.wtSessionTicketKey.toUHexString()}") + delay(2000) + SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect() } internal fun launchPacketProcessor(rawInput: ByteReadPacket): Job = launch(CoroutineName("Incoming Packet handler")) { diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt index 788b760cb..b60278326 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt @@ -5,6 +5,7 @@ import kotlinx.atomicfu.atomic import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.toByteArray import net.mamoe.mirai.BotAccount +import net.mamoe.mirai.data.OnlineStatus import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.network.protocol.packet.Tlv import net.mamoe.mirai.qqandroid.utils.Context @@ -15,6 +16,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.cryptor.ECDH import net.mamoe.mirai.utils.cryptor.contentToString +import net.mamoe.mirai.utils.getValue import net.mamoe.mirai.utils.io.hexToBytes import net.mamoe.mirai.utils.io.read import net.mamoe.mirai.utils.io.readUShortLVByteArray @@ -50,7 +52,9 @@ internal open class QQAndroidClient( return "QQAndroidClient(account=$account, ecdh=$ecdh, device=$device, tgtgtKey=${tgtgtKey.contentToString()}, randomKey=${randomKey.contentToString()}, miscBitMap=$miscBitMap, mainSigMap=$mainSigMap, subSigMap=$subSigMap, openAppId=$openAppId, apkVersionName=${apkVersionName.contentToString()}, loginState=$loginState, appClientVersion=$appClientVersion, networkType=$networkType, apkSignatureMd5=${apkSignatureMd5.contentToString()}, protocolVersion=$protocolVersion, apkId=${apkId.contentToString()}, t150=${t150?.contentToString()}, rollbackSig=${rollbackSig?.contentToString()}, ipFromT149=${ipFromT149?.contentToString()}, timeDifference=$timeDifference, uin=$uin, t530=${t530?.contentToString()}, t528=${t528?.contentToString()}, ksid='$ksid', pwdFlag=$pwdFlag, loginExtraData=$loginExtraData, wFastLoginInfo=$wFastLoginInfo, reserveUinInfo=$reserveUinInfo, wLoginSigInfo=$wLoginSigInfo, tlv113=${tlv113?.contentToString()}, qrPushSig=${qrPushSig.contentToString()}, mainDisplayName='$mainDisplayName')" } - val context by context.unsafeWeakRef() + var onlineStatus: OnlineStatus = OnlineStatus.ONLINE + + val context: Context by context.unsafeWeakRef() val bot: QQAndroidBot by bot.unsafeWeakRef() var tgtgtKey: ByteArray = ByteArray(16) // generateTgtgtKey(device.guid) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt index 5905b9afd..ba352b960 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt @@ -2,10 +2,21 @@ package net.mamoe.mirai.qqandroid.network.io import kotlinx.io.charsets.Charset import kotlinx.io.core.* +import kotlinx.io.pool.useInstance +import net.mamoe.mirai.utils.io.ByteArrayPool +import net.mamoe.mirai.utils.io.readRemainingBytes import kotlin.reflect.KClass private val CharsetGBK = Charset.forName("GBK") +fun buildJcePacket(stringCharset: Charset = CharsetGBK, block: JceOutput.() -> Unit): ByteReadPacket { + return JceOutput(stringCharset).apply(block).build() +} + +fun BytePacketBuilder.writeJcePacket(stringCharset: Charset = CharsetGBK, block: JceOutput.() -> Unit) { + return this.writePacket(buildJcePacket(stringCharset, block)) +} + /** * * From: com.qq.taf.jce.JceOutputStream @@ -13,9 +24,11 @@ private val CharsetGBK = Charset.forName("GBK") @Suppress("unused", "MemberVisibilityCanBePrivate") @UseExperimental(ExperimentalIoApi::class) class JceOutput( - private val stringCharset: Charset = CharsetGBK, - private val output: Output = BytePacketBuilder() + private val stringCharset: Charset = CharsetGBK ) { + private val output: BytePacketBuilder = BytePacketBuilder() + + fun build(): ByteReadPacket = output.build() fun close() = output.close() fun flush() = output.flush() @@ -197,10 +210,36 @@ class JceOutput( is FloatArray -> writeFully(v, tag) is DoubleArray -> writeFully(v, tag) is Array<*> -> writeFully(v, tag) + is String -> writeString(v, tag) + +// +// is ByteReadPacket -> ByteArrayPool.useInstance { +// v.readAvailable(it) +// writeFully(it, tag) +// } else -> error("unsupported type: ${v.getClassName()}") } } + fun write(v: Int, tag: Int) = writeInt(v, tag) + fun write(v: Byte, tag: Int) = writeByte(v, tag) + fun write(v: Short, tag: Int) = writeShort(v, tag) + fun write(v: Long, tag: Int) = writeLong(v, tag) + fun write(v: Float, tag: Int) = writeFloat(v, tag) + fun write(v: Double, tag: Int) = writeDouble(v, tag) + fun write(v: String, tag: Int) = writeString(v, tag) + fun write(v: Boolean, tag: Int) = writeBoolean(v, tag) + fun write(v: Collection<*>, tag: Int) = writeCollection(v, tag) + fun write(v: Map<*, *>, tag: Int) = writeMap(v, tag) + fun write(v: ByteArray, tag: Int) = writeFully(v, tag) + fun write(v: IntArray, tag: Int) = writeFully(v, tag) + fun write(v: BooleanArray, tag: Int) = writeFully(v, tag) + fun write(v: LongArray, tag: Int) = writeFully(v, tag) + fun write(v: ShortArray, tag: Int) = writeFully(v, tag) + fun write(v: Array<*>, tag: Int) = writeFully(v, tag) + fun write(v: FloatArray, tag: Int) = writeFully(v, tag) + fun write(v: DoubleArray, tag: Int) = writeFully(v, tag) + @PublishedApi internal companion object { const val BYTE: Int = 0 diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt index 6c84e678c..73ebe85b4 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt @@ -1,5 +1,7 @@ package net.mamoe.mirai.qqandroid.network.io +import kotlinx.io.core.BytePacketBuilder + abstract class JceStruct { - abstract fun writeTo(p0: JceOutput) + abstract fun writeTo(builder: JceOutput) } \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt new file mode 100644 index 000000000..fc10c55fe --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/RequestPacket.kt @@ -0,0 +1,32 @@ +package net.mamoe.mirai.qqandroid.network.protocol.jce + +import net.mamoe.mirai.qqandroid.network.io.JceOutput +import net.mamoe.mirai.qqandroid.network.io.JceStruct + +private val EMPTY_MAP = mapOf() + +class RequestPacket( + val sBuffer: ByteArray, + val cPacketType: Byte = 0, + val iMessageType: Int = 0, + val iRequestId: Int = 0, + val iTimeout: Int = 3000, + val iVersion: Short = 3, + val context: Map = EMPTY_MAP, + val sFuncName: String = "", + val sServantName: String = "", + val status: Map = EMPTY_MAP +) : JceStruct() { + override fun writeTo(builder: JceOutput) { + builder.write(this.iVersion, 1) + builder.write(this.cPacketType, 2) + builder.write(this.iMessageType, 3) + builder.write(this.iRequestId, 4) + builder.write(this.sServantName, 5) + builder.write(this.sFuncName, 6) + builder.write(this.sBuffer, 7) + builder.write(this.iTimeout, 8) + builder.write(this.context, 9) + builder.write(this.status, 10) + } +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt new file mode 100644 index 000000000..727155432 --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt @@ -0,0 +1,123 @@ +package net.mamoe.mirai.qqandroid.network.protocol.jce + +import net.mamoe.mirai.qqandroid.network.io.JceOutput +import net.mamoe.mirai.qqandroid.network.io.JceStruct + +class SvcReqRegister( + val bIsOnline: Byte = 0, + val bIsSetStatus: Byte = 0, + val bIsShowOnline: Byte = 0, + val bKikPC: Byte = 0, + val bKikWeak: Byte = 0, + val bOnlinePush: Byte = 0, + val bOpenPush: Byte = 1, + val bRegType: Byte = 0, + val bSetMute: Byte = 0, + val bSlientPush: Byte = 0, + val bytes_0x769_reqbody: ByteArray? = null, + val cConnType: Byte = 0, + val cNetType: Byte = 0, + val iLargeSeq: Long = 0L, + val iLastWatchStartTime: Long = 0L, + val iLocaleID: Int = 2052, + val iOSVersion: Long = 0L, + val iStatus: Int = 11, + val lBid: Long = 0L, + val lCpId: Long = 0L, + val lUin: Long = 0L, + val sBuildVer: String? = "", + val sChannelNo: String? = "", + val sOther: String = "", + val strDevName: String? = "", + val strDevType: String? = "", + val strIOSIdfa: String? = "", + val strOSVer: String? = "", + val strVendorName: String? = "", + val strVendorOSName: String? = "", + val timeStamp: Long = 0L, + val uNewSSOIp: Long = 0L, + val uOldSSOIp: Long = 0L, + val vecDevParam: ByteArray? = null, + val vecGuid: ByteArray? = null, + val vecServerBuf: ByteArray? = null +) : JceStruct() { + + override fun writeTo(builder: JceOutput) { + builder.write(lUin, 0) + builder.write(lBid, 1) + builder.write(cConnType, 2) + builder.write(sOther, 3) + builder.write(iStatus, 4) + builder.write(bOnlinePush, 5) + builder.write(bIsOnline, 6) + builder.write(bIsShowOnline, 7) + builder.write(bKikPC, 8) + builder.write(bKikWeak, 9) + builder.write(timeStamp, 10) + builder.write(iOSVersion, 11) + builder.write(cNetType, 12) + if (sBuildVer != null) { + builder.write(sBuildVer, 13) + } + + builder.write(bRegType, 14) + if (vecDevParam != null) { + builder.write(vecDevParam, 15) + } + + if (vecGuid != null) { + builder.write(vecGuid, 16) + } + + builder.write(iLocaleID, 17) + builder.write(bSlientPush, 18) + if (strDevName != null) { + builder.write(strDevName, 19) + } + + if (strDevType != null) { + builder.write(strDevType, 20) + } + + if (strOSVer != null) { + builder.write(strOSVer, 21) + } + + builder.write(bOpenPush, 22) + builder.write(iLargeSeq, 23) + builder.write(iLastWatchStartTime, 24) + // if (this.vecBindUin != null) { + // builder.write(this.vecBindUin, 25) + // } + + builder.write(uOldSSOIp, 26) + builder.write(uNewSSOIp, 27) + if (sChannelNo != null) { + builder.write(sChannelNo, 28) + } + + builder.write(lCpId, 29) + if (strVendorName != null) { + builder.write(strVendorName, 30) + } + + if (strVendorOSName != null) { + builder.write(strVendorOSName, 31) + } + + if (strIOSIdfa != null) { + builder.write(strIOSIdfa, 32) + } + + if (bytes_0x769_reqbody != null) { + builder.write(bytes_0x769_reqbody, 33) + } + + builder.write(bIsSetStatus, 34) + if (vecServerBuf != null) { + builder.write(vecServerBuf, 35) + } + + builder.write(bSetMute, 36) + } +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt new file mode 100644 index 000000000..d68d3fb42 --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/uni.kt @@ -0,0 +1,12 @@ +package net.mamoe.mirai.qqandroid.network.protocol.jce + +import kotlinx.io.core.BytePacketBuilder +import net.mamoe.mirai.qqandroid.network.io.JceOutput +import net.mamoe.mirai.qqandroid.network.io.buildJcePacket +import net.mamoe.mirai.qqandroid.network.io.writeJcePacket + +fun BytePacketBuilder.writeUniRequestPacket(requestPacket: RequestPacket) { + writeJcePacket { + requestPacket.writeTo(this) + } +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/MessageMicro.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/MessageMicro.kt new file mode 100644 index 000000000..2c7d385d9 --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/MessageMicro.kt @@ -0,0 +1,9 @@ +package net.mamoe.mirai.qqandroid.network.protocol.packet + +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.protobuf.ProtoBuf + +interface MessageMicro + + +fun T.toByteArray(serializer: SerializationStrategy): ByteArray = ProtoBuf.dump(serializer, this) \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt index b1c467364..618853670 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt @@ -31,8 +31,8 @@ internal class OutgoingPacket constructor( } } -private val KEY_16_ZEROS = ByteArray(16) -private val EMPTY_BYTE_ARRAY = ByteArray(0) +internal val KEY_16_ZEROS = ByteArray(16) +internal val EMPTY_BYTE_ARRAY = ByteArray(0) /** * 最外层的包. 结构适用于登录之后的过程. @@ -61,16 +61,31 @@ private val EMPTY_BYTE_ARRAY = ByteArray(0) * 31 39 39 34 37 30 31 30 32 31 * 18 5D 8F 17 7D 67 71 61 FE DB 30 A4 4D 16 DD 0E 8D 84 0A F2 44 BE FB BB 11 BB B4 AC 79 50 50 9F 4C 99 CC 77 0B AA B6 E0 06 0C F7 91 79 99 57 31 3D EF 38 92 2C C8 81 33 79 83 FF C6 2F BA 18 2A 33 F8 D9 4E CD 62 07 D8 08 B7 1A 1E C7 EB AC AB B4 1E C9 9D A9 15 9C 29 29 2A 99 F6 BB D0 43 65 D6 5E 9C 93 A8 8D 17 08 5B 6A 29 92 58 6A 75 C9 B5 45 B3 0E A5 D3 52 8F 9A A4 88 36 A0 14 3A 21 F2 46 C3 91 66 A3 73 67 6A 3E F7 9D 8E 44 52 87 7B 8A C7 1B E2 D3 98 62 E8 25 30 2A 43 5C 5A B2 C6 45 F5 39 EC 85 81 BF 7D 22 4C E8 01 87 92 48 38 06 6B A0 83 70 0B 51 ED CF 7A FF E2 F2 06 3E A7 95 4E E5 29 23 32 1C FE 79 C6 08 C5 7A 39 B9 AF CD 4F 80 3E 5D 74 4D 0B E1 10 33 8D F0 54 8E 0E 22 96 B4 06 7F 29 01 1E CA 30 35 FD 8A 2E 51 04 20 79 7B 08 DC DF F6 64 21 6B C5 95 34 B3 40 D2 E8 CE BB DC 69 89 75 62 A6 0B 4A 49 9D 90 BA 68 2B BD 8A 50 2D 68 6B 56 40 0C 39 F2 08 20 1B EB A4 A5 20 1D 1F 7E FA 4B B8 2E 58 79 2A 16 54 26 6C C8 44 6C 4F 64 2D 5C 0C 47 2E 90 13 A9 D7 33 4A 51 17 6E 3F 3E 48 AE 39 D8 45 05 2C 0C 3C 9F 92 39 DB 62 B3 BB 64 EE 7E 91 C5 84 92 10 96 D9 F1 13 02 94 00 EA DA 87 7C 85 7B 68 BA 8D A1 AB F5 CD 9C EB 4C CD A0 38 78 43 80 DD E5 1D 28 25 1F F0 25 EF 0D 95 91 0F 21 5D 41 06 00 03 48 77 E0 98 09 3E 04 5A B0 93 63 3B AE 8E 49 0C C2 12 BA DD C3 5A ED FF 68 98 22 C4 5E F6 1E 85 57 15 E8 7E 26 22 E3 70 C2 57 F4 CE 2F CB C4 DC 39 4A 9C FE DE 27 18 D3 36 66 88 92 D7 69 D0 04 8E 93 9B AD E9 2E 5A 2C 91 CD 28 DF BE 62 CF 2C 72 8E FD A9 1F 0E 8E 00 9E 54 28 50 25 0C E7 DC 98 85 C9 B3 59 A8 97 F5 2E 7F 44 4C 43 3C C4 65 E5 AB DB 5B 3C 50 2D 53 B3 EA 74 3C 39 F4 0A 52 31 34 30 F5 E6 82 CD 36 D9 */ -internal inline fun PacketFactory<*, *>.buildOutgingPacket( +@UseExperimental(MiraiInternalAPI::class) +internal inline fun PacketFactory<*>.buildOutgingPacket( client: QQAndroidClient, - subAppId: Long, - extraData: ByteArray = EMPTY_BYTE_ARRAY, name: String? = null, id: PacketId = this.id, - ssoExtraData: ByteReadPacket = BRP_STUB, + key: ByteArray, body: BytePacketBuilder.(sequenceId: Int) -> Unit -){ +): OutgoingPacket { + val sequenceId: Int = client.nextSsoSequenceId() + return OutgoingPacket(name, id, sequenceId, buildPacket { + writeIntLVPacket(lengthOffset = { it + 4 }) { + writeInt(0x0B) + writeByte(1) + writeInt(sequenceId) + writeByte(0) + client.uin.toString().let { + writeInt(it.length + 4) + writeStringUtf8(it) + } + encryptAndWrite(key) { + body(sequenceId) + } + } + }) } /** @@ -92,7 +107,7 @@ internal inline fun PacketFactory<*, *>.buildOutgingPacket( * byte[] body encrypted by 16 zero */ @UseExperimental(MiraiInternalAPI::class) -internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket( +internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( client: QQAndroidClient, subAppId: Long, extraData: ByteArray = EMPTY_BYTE_ARRAY, @@ -214,7 +229,7 @@ private inline fun BytePacketBuilder.writeLoginSsoPacket( * * byte[] body encrypted by [sessionKey] */ -internal inline fun PacketFactory<*, *>.buildSessionOutgoingPacket( +internal inline fun PacketFactory<*>.buildSessionOutgoingPacket( uinAccount: String, sessionKey: DecrypterByteArray, body: BytePacketBuilder.() -> Unit diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt index 53d4d9163..ea37c371e 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt @@ -25,9 +25,7 @@ import kotlin.jvm.JvmName * @param TDecrypter 服务器回复包解密器 */ @UseExperimental(ExperimentalUnsignedTypes::class) -internal abstract class PacketFactory(val decrypterType: DecrypterType) { - - // TODO: 2020/1/12 Decrypter 多余. 需要删除 +internal abstract class PacketFactory { @Suppress("PropertyName") internal var _id: PacketId = NullPacketId @@ -44,20 +42,20 @@ internal abstract class PacketFactory PacketFactory.decode(bot: QQAndroidBot, packet: ByteReadPacket): P = packet.decode(bot) +private suspend inline fun

PacketFactory

.decode(bot: QQAndroidBot, packet: ByteReadPacket): P = packet.decode(bot) private val DECRYPTER_16_ZERO = ByteArray(16) internal typealias PacketConsumer = suspend (packet: Packet, packetId: PacketId, ssoSequenceId: Int) -> Unit @UseExperimental(ExperimentalUnsignedTypes::class) -internal object KnownPacketFactories : List> by mutableListOf( +internal object KnownPacketFactories : List> by mutableListOf( LoginPacket ) { - fun findPacketFactory(commandName: String): PacketFactory<*, *> = this.first { it.id.commandName == commandName } + fun findPacketFactory(commandName: String): PacketFactory<*> = this.first { it.id.commandName == commandName } - fun findPacketFactory(commandId: Int): PacketFactory<*, *> = this.first { it.id.commandName == commandName } + fun findPacketFactory(commandId: Int): PacketFactory<*> = this.first { it.id.commandName == commandName } // do not inline. Exceptions thrown will not be reported correctly suspend fun parseIncomingPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) = diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt index be80b05f2..20a9c63b4 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt @@ -11,8 +11,6 @@ import net.mamoe.mirai.qqandroid.utils.GuidSource import net.mamoe.mirai.qqandroid.utils.MacOrAndroidIdChangeFlag import net.mamoe.mirai.qqandroid.utils.guidFlag import net.mamoe.mirai.utils.MiraiInternalAPI -import net.mamoe.mirai.utils.cryptor.DecrypterByteArray -import net.mamoe.mirai.utils.cryptor.DecrypterType import net.mamoe.mirai.utils.cryptor.contentToString import net.mamoe.mirai.utils.cryptor.decryptBy import net.mamoe.mirai.utils.currentTimeMillis @@ -20,16 +18,19 @@ import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.discardExact -class LoginPacketDecrypter(override val value: ByteArray) : DecrypterByteArray { - companion object : DecrypterType -} - +/** + * OicqRequest + */ @UseExperimental(ExperimentalUnsignedTypes::class) -internal object LoginPacket : PacketFactory(LoginPacketDecrypter) { +internal object LoginPacket : PacketFactory() { init { this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login") } + fun hahahaha() { + + } + object SubCommand9 { private const val appId = 16L private const val subAppId = 537062845L @@ -60,6 +61,8 @@ internal object LoginPacket : PacketFactory() { + + internal object Response : Packet + + operator fun invoke( + client: QQAndroidClient, + regPushReason: RegPushReason = RegPushReason.setOnlineStatus + ): OutgoingPacket = buildOutgingPacket(client, key = client.wLoginSigInfo.wtSessionTicketKey) { + writeUniRequestPacket( + RequestPacket( + sServantName = "PushService", + sFuncName = "SvcReqRegister", + sBuffer = buildJcePacket { + writeMap( + mapOf( + "SvcReqRegister" to buildJcePacket { + writeJceStruct( + SvcReqRegister( + cConnType = 0, + lBid = 1 or 2 or 4, + lUin = client.uin, + iStatus = client.onlineStatus.id, + bKikPC = 0, // 是否把 PC 踢下线 + bKikWeak = 0, + timeStamp = currentTimeSeconds, // millis or seconds?? + iLargeSeq = 0, + bRegType = + if (regPushReason == RegPushReason.appRegister || + regPushReason == RegPushReason.fillRegProxy || + regPushReason == RegPushReason.createDefaultRegInfo || + regPushReason == RegPushReason.setOnlineStatus + ) { + 0 + } else { + 1 + }.toByte(), + bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0, + iOSVersion = client.device.version.sdk.toLong(), + cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0, + vecGuid = client.device.guid, + strDevName = client.device.model.encodeToString(), + strDevType = client.device.model.encodeToString(), + strOSVer = client.device.version.release.encodeToString(), + + // register 时还需要 + /* + var44.uNewSSOIp = field_127445; + var44.uOldSSOIp = field_127444; + var44.strVendorName = ROMUtil.getRomName(); + var44.strVendorOSName = ROMUtil.getRomVersion(20); + */ + bytes_0x769_reqbody = ProtoBuf.dump( + Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody( + rpt_config_list = listOf( + Oidb0x769.ConfigSeq( + type = 46, + version = 4 + ), + Oidb0x769.ConfigSeq( + type = 283, + version = 0 + ) + ) + ) + ), + bSetMute = 0 + ), 0 + ) + }.readBytes() + ), 0 + ) + }.readBytes() + ) + ) + } + + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { + return Response + } +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/TransEmpPacket.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/TransEmpPacket.kt index 2cc97a03b..9d9fd86fe 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/TransEmpPacket.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/TransEmpPacket.kt @@ -8,7 +8,7 @@ import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.protocol.packet.* import net.mamoe.mirai.utils.io.toReadPacket -internal object TransEmpPacket : PacketFactory(LoginPacketDecrypter) { +internal object TransEmpPacket : PacketFactory() { init { _id = PacketId(0x0812, "wtlogin.trans_emp") diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/command/GetPublicAccountDetailInfo.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/command/GetPublicAccountDetailInfo.kt new file mode 100644 index 000000000..19e34a7ed --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/command/GetPublicAccountDetailInfo.kt @@ -0,0 +1,19 @@ +package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.command + +import kotlinx.serialization.Serializable +import net.mamoe.mirai.qqandroid.network.protocol.packet.MessageMicro + +/** + * oidb_cmd0xcf8$GetPublicAccountDetailInfoRequest + */ +@Serializable +class GetPublicAccountDetailInfoRequest( + val seqno: Int, // uint + val uinLong: Long, + val version: Int, // uint + val versionInfo: String +) : MessageMicro + +class GetPublicAccountDetailInfoResponse( + +) : MessageMicro \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/oidb0x769/Oidb0x769.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/oidb0x769/Oidb0x769.kt new file mode 100644 index 000000000..da7aed64b --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/oidb0x769/Oidb0x769.kt @@ -0,0 +1,85 @@ +package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769 + +import kotlinx.serialization.SerialId +import kotlinx.serialization.Serializable + +class Oidb0x769 { + @Serializable + class RequestBody( + @SerialId(1) val rpt_config_list: List + // @SerialId(2) val msg_device_info: DeviceInfo, + // @SerialId(3) val str_info: String = "", + // @SerialId(4) val province: String, + // @SerialId(5) val city: String, + // @SerialId(6) val req_debug_msg: Int = 0, + // @SerialId(101) val query_uin_package_usage_req: QueryUinPackageUsageReq + ) + + @Serializable + class QueryUinPackageUsageReq( + @SerialId(1) val type: Int, + @SerialId(2) val uinFileSize: Long = 0 + ) + + @Serializable + class ConfigSeq( + @SerialId(1) val type: Int, // uint + @SerialId(2) val version: Int // uint + ) + + @Serializable + class DeviceInfo( + @SerialId(1) val brand: String, + @SerialId(2) val model: String + //@SerialId(3) val os: OS, + //@SerialId(4) val cpu: CPU, + //@SerialId(5) val memory: Memory, + //@SerialId(6) val storage: Storage, + //@SerialId(7) val screen: Screen, + //@SerialId(8) val camera: Camera + ) + + @Serializable + class OS( + @SerialId(1) val type: Int = 1, + @SerialId(2) val version: String, + @SerialId(3) val sdk: String, + @SerialId(4) val kernel: String, + @SerialId(5) val rom: String + ) + + @Serializable + class Camera( + @SerialId(1) val primary: Long, + @SerialId(2) val secondary: Long, + @SerialId(3) val flag: Boolean + ) + + @Serializable + class CPU( + @SerialId(1) val model: String, + @SerialId(2) val frequency: Int, + @SerialId(3) val cores: Int + ) + + @Serializable + class Memory( + @SerialId(1) val total: Int, + @SerialId(2) val process: Int + ) + + @Serializable + class Screen( + @SerialId(1) val model: String, + @SerialId(2) val width: Int, + @SerialId(3) val height: Int, + @SerialId(4) val dpi: Int, + @SerialId(5) val multiTouch: Boolean + ) + + @Serializable + class Storage( + @SerialId(1) val builtin: Int, + @SerialId(2) val external: Int + ) +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/sso/OidbSsoPackage.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/sso/OidbSsoPackage.kt new file mode 100644 index 000000000..6ceea7a87 --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/oidb/sso/OidbSsoPackage.kt @@ -0,0 +1,22 @@ +package net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.sso + +import kotlinx.serialization.SerialId +import kotlinx.serialization.Serializable +import net.mamoe.mirai.qqandroid.network.protocol.packet.MessageMicro + +/** + * oidb_sso$OIDBSSOPkg + */ +@Serializable +class OidbSsoPackage( + @SerialId(1) val command: Int, // uint + @SerialId(2) val serviceType: Int, // uint + @SerialId(3) val result: Int, // uint + @SerialId(4) val bodyBuffer: ByteArray, + @SerialId(5) val errorMessage: String, + @SerialId(6) val clientVersion: String +) : MessageMicro + + + + diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/DeviceInfo.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/DeviceInfo.kt index cb8831ec0..0094bea83 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/DeviceInfo.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/DeviceInfo.kt @@ -3,7 +3,10 @@ package net.mamoe.mirai.qqandroid.utils import kotlinx.serialization.SerialId import kotlinx.serialization.Serializable import kotlinx.serialization.protobuf.ProtoBuf +import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769 import net.mamoe.mirai.utils.cryptor.contentToString +import net.mamoe.mirai.utils.getValue +import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.unsafeWeakRef abstract class DeviceInfo( @@ -84,7 +87,18 @@ abstract class DeviceInfo( val incremental: ByteArray val release: ByteArray val codename: ByteArray + val sdk: Int } +} - -} \ No newline at end of file +/* +fun DeviceInfo.toOidb0x769DeviceInfo() : Oidb0x769.DeviceInfo = Oidb0x769.DeviceInfo( + brand = brand.encodeToString(), + model = model.encodeToString(), + os = Oidb0x769.OS( + version = version.release.encodeToString(), + sdk = version.sdk.toString(), + kernel = version.kernel + ) +) +*/ \ No newline at end of file diff --git a/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt b/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt index b1e0fcff3..ed924c03a 100644 --- a/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt +++ b/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/SystemDeviceInfo.kt @@ -35,6 +35,7 @@ actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo( override val incremental: ByteArray get() = "5891938".toByteArray() override val release: ByteArray get() = "10".toByteArray() override val codename: ByteArray get() = "REL".toByteArray() + override val sdk: Int get() = 29 } } diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayPool.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayPool.kt index f3b23df58..27ad698bf 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayPool.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayPool.kt @@ -4,7 +4,7 @@ import kotlinx.io.pool.DefaultPool import kotlinx.io.pool.ObjectPool internal const val DEFAULT_BYTE_ARRAY_POOL_SIZE = 256 -internal const val DEFAULT_BYTE_ARRAY_SIZE = 4096 +internal const val DEFAULT_BYTE_ARRAY_SIZE = 8192 val ByteArrayPool: ObjectPool = ByteArrayPoolImpl diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayUtil.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayUtil.kt index 74906150c..b7a83c4a4 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayUtil.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/ByteArrayUtil.kt @@ -2,8 +2,6 @@ package net.mamoe.mirai.utils.io -import kotlinx.io.charsets.Charset -import kotlinx.io.charsets.Charsets import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.String import kotlinx.io.core.use @@ -47,7 +45,7 @@ fun UByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: In } } -fun ByteArray.encodeToString(charset: Charset = Charsets.UTF_8): String = String(this, charset = charset) +fun ByteArray.encodeToString(): String = String(this) fun ByteArray.toReadPacket(offset: Int = 0, length: Int = this.size) = ByteReadPacket(this, offset = offset, length = length)