QQA Debugging update

This commit is contained in:
Him188 2020-01-23 19:58:59 +08:00
parent f4def5ef58
commit 6bd22da100
7 changed files with 47 additions and 66 deletions

View File

@ -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.KnownPacketFactories
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket 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.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.RegPushReason
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
@ -101,12 +100,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
*/ */
suspend fun parsePacket(input: Input) { suspend fun parsePacket(input: Input) {
try { 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) { if (PacketReceivedEvent(packet).broadcast().cancelled) {
return@parseIncomingPacket return@parseIncomingPacket
} }
packetListeners.forEach { listener -> packetListeners.forEach { listener ->
if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) { if (listener.filter(commandName, sequenceId) && packetListeners.remove(listener)) {
listener.complete(packet) listener.complete(packet)
} }
} }
@ -202,7 +201,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
} }
suspend fun <E : Packet> OutgoingPacket.sendAndExpect(): E { suspend fun <E : Packet> OutgoingPacket.sendAndExpect(): E {
val handler = PacketListener(packetId = packetId, sequenceId = sequenceId) val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
packetListeners.addLast(handler) packetListeners.addLast(handler)
//println(delegate.readBytes().toUHexString()) //println(delegate.readBytes().toUHexString())
println("Sending length=" + delegate.remaining) println("Sending length=" + delegate.remaining)
@ -217,10 +216,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
@PublishedApi @PublishedApi
internal inner class PacketListener( internal inner class PacketListener(
val packetId: PacketId, val commandName: String,
val sequenceId: Int val sequenceId: Int
) : CompletableDeferred<Packet> by CompletableDeferred(supervisor) { ) : 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() override suspend fun awaitDisconnection() = supervisor.join()

View File

@ -6,8 +6,6 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.QQAndroidClient 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.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import net.mamoe.mirai.utils.cryptor.encryptAndWrite import net.mamoe.mirai.utils.cryptor.encryptAndWrite
@ -23,12 +21,12 @@ import net.mamoe.mirai.utils.io.writeQQ
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal class OutgoingPacket constructor( internal class OutgoingPacket constructor(
name: String?, name: String?,
val packetId: PacketId, val commandName: String,
val sequenceId: Int, val sequenceId: Int,
val delegate: ByteReadPacket val delegate: ByteReadPacket
) { ) {
val name: String by lazy { 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( internal inline fun PacketFactory<*>.buildOutgingPacket(
client: QQAndroidClient, client: QQAndroidClient,
name: String? = null, name: String? = null,
id: PacketId = this.id, commandName: String = this.commandName,
key: ByteArray, key: ByteArray,
body: BytePacketBuilder.(sequenceId: Int) -> Unit body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket { ): OutgoingPacket {
val sequenceId: Int = client.nextSsoSequenceId() val sequenceId: Int = client.nextSsoSequenceId()
return OutgoingPacket(name, id, sequenceId, buildPacket { return OutgoingPacket(name, commandName, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x0B) writeInt(0x0B)
writeByte(1) writeByte(1)
@ -113,13 +111,13 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
bodyType: Byte, bodyType: Byte,
extraData: ByteArray = EMPTY_BYTE_ARRAY, extraData: ByteArray = EMPTY_BYTE_ARRAY,
name: String? = null, name: String? = null,
id: PacketId = this.id, commandName: String = this.commandName,
key: ByteArray = KEY_16_ZEROS, key: ByteArray = KEY_16_ZEROS,
body: BytePacketBuilder.(sequenceId: Int) -> Unit body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket { ): OutgoingPacket {
val sequenceId: Int = client.nextSsoSequenceId() val sequenceId: Int = client.nextSsoSequenceId()
return OutgoingPacket(name, id, sequenceId, buildPacket { return OutgoingPacket(name, commandName, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x00_00_00_0A) writeInt(0x00_00_00_0A)
writeByte(bodyType) writeByte(bodyType)
@ -168,10 +166,10 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
* byte[] body() * byte[] body()
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
internal inline fun BytePacketBuilder.writeLoginSsoPacket( internal inline fun BytePacketBuilder.writeSsoPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, subAppId: Long,
packetId: PacketId, commandName: String,
extraData: ByteReadPacket = BRP_STUB, extraData: ByteReadPacket = BRP_STUB,
sequenceId: Int, sequenceId: Int,
body: BytePacketBuilder.() -> Unit body: BytePacketBuilder.() -> Unit
@ -187,7 +185,7 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
writeInt((extraData.remaining + 4).toInt()) writeInt((extraData.remaining + 4).toInt())
writePacket(extraData) writePacket(extraData)
} }
packetId.commandName.let { commandName.let {
writeInt(it.length + 4) writeInt(it.length + 4)
writeStringUtf8(it) writeStringUtf8(it)
} }
@ -269,7 +267,7 @@ internal inline fun PacketFactory<*>.buildSessionOutgoingPacket(
internal fun BytePacketBuilder.writeOicqRequestPacket( internal fun BytePacketBuilder.writeOicqRequestPacket(
client: QQAndroidClient, client: QQAndroidClient,
encryptMethod: EncryptMethod, encryptMethod: EncryptMethod,
packetId: PacketId, commandId: Int,
bodyBlock: BytePacketBuilder.() -> Unit bodyBlock: BytePacketBuilder.() -> Unit
) { ) {
val body = encryptMethod.makeBody(client, bodyBlock) val body = encryptMethod.makeBody(client, bodyBlock)
@ -278,7 +276,7 @@ internal fun BytePacketBuilder.writeOicqRequestPacket(
writeByte(0x02) // head writeByte(0x02) // head
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
writeShort(client.protocolVersion) writeShort(client.protocolVersion)
writeShort(packetId.commandId.toShort()) writeShort(commandId.toShort())
writeShort(1) // const?? writeShort(1) // const??
writeQQ(client.uin) writeQQ(client.uin)
writeByte(3) // originally const writeByte(3) // originally const

View File

@ -6,13 +6,12 @@ import kotlinx.serialization.Serializable
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory 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 import net.mamoe.mirai.utils.currentTimeSeconds
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>() { internal object ImagePacket : PacketFactory<ImagePacket.RequestImgUrlResponse>() {
init { 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) if (req is UploadImgReq)
return Cmd0x352Packet(1, req, null, null, networkType) return Cmd0x352Packet(1, req, null, null, networkType)
if (req is GetImgUrlReq) if (req is GetImgUrlReq)

View File

@ -25,7 +25,7 @@ import net.mamoe.mirai.utils.io.discardExact
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() { internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
init { init {
this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login") this._commandName = "wtlogin.login"
} }
object SubCommand9 { object SubCommand9 {
@ -36,8 +36,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
operator fun invoke( operator fun invoke(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId -> ): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { sequenceId ->
writeLoginSsoPacket(client, subAppId, id, sequenceId = sequenceId) { writeSsoPacket(client, subAppId, commandName, sequenceId = sequenceId) {
writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), id) { writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), 0x0810) {
writeShort(9) // subCommand writeShort(9) // subCommand
writeShort(17) // count of TLVs, probably ignored by server? writeShort(17) // count of TLVs, probably ignored by server?
//writeShort(LoginType.PASSWORD.value.toShort()) //writeShort(LoginType.PASSWORD.value.toShort())
@ -564,20 +564,3 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
} }
} }
} }
@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")
}

View File

@ -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.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket 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.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.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.io.debugPrint import net.mamoe.mirai.utils.io.debugPrint
@ -40,10 +40,10 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
internal object Response : Packet internal object Response : Packet
const val subAppId = 537062845L private const val subAppId = 537062845L
init { init {
_id = PacketId(0, "StatSvc.register") _commandName = "StatSvc.register"
} }
operator fun invoke( operator fun invoke(
@ -55,8 +55,8 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
extraData = client.wLoginSigInfo.d2.data, extraData = client.wLoginSigInfo.d2.data,
key = client.wLoginSigInfo.d2Key key = client.wLoginSigInfo.d2Key
) { sequenceId -> ) { sequenceId ->
writeLoginSsoPacket( writeSsoPacket(
client, subAppId = subAppId, packetId = id, client, subAppId = subAppId, commandName = commandName,
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
) { ) {
writeUniRequestPacket { writeUniRequestPacket {

View File

@ -10,7 +10,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.*
internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() { internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
init { init {
_id = PacketId(0x0812, "wtlogin.trans_emp") _commandName = "wtlogin.trans_emp"
} }
private const val appId = 16L private const val appId = 16L
@ -20,7 +20,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
fun SubCommand1( fun SubCommand1(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) { ): 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 // oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody
} }