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.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()

View File

@ -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

View File

@ -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, req, null, null, networkType)
if (req is GetImgUrlReq)

View File

@ -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())
@ -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.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 {

View File

@ -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
}