Commit 8eb3daca authored by Him188's avatar Him188

QQA Debugging update

parent d6822b7d
package net.mamoe.mirai.qqandroid.network.io package net.mamoe.mirai.qqandroid.network.io
import kotlinx.io.core.* import kotlinx.io.core.*
import kotlinx.io.pool.ObjectPool
import net.mamoe.mirai.utils.io.readString import net.mamoe.mirai.utils.io.readString
import net.mamoe.mirai.utils.io.toIoBuffer
import kotlin.experimental.and import kotlin.experimental.and
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
inline class JceHead(private val value: Long) { inline class JceHead(private val value: Long) {
constructor(tag: Int, type: Byte) : this(tag.shl(32).toLong() and type.toLong()) constructor(tag: Int, type: Byte) : this(tag.toLong().shl(32) or type.toLong())
val tag: Int get() = (value ushr 32).toInt() val tag: Int get() = (value ushr 32).toInt()
val type: Byte get() = value.toUInt().toByte() val type: Byte get() = value.toUInt().toByte()
} }
fun ByteArray.asJceInput(): JceInput = JceInput(this.toIoBuffer())
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
class JceInput( class JceInput(
@PublishedApi @PublishedApi
internal val input: Input internal val input: IoBuffer,
) { private val pool: ObjectPool<IoBuffer> = IoBuffer.Pool
) : Closeable {
constructor(input: Input) : this(IoBuffer.Pool.borrow().also { input.readAvailable(it) })
override fun close() {
input.release(pool)
}
@PublishedApi
internal fun readHead(): JceHead = input.readHead()
@PublishedApi @PublishedApi
internal fun readHead(): JceHead = input.run { internal fun peakHead(): JceHead = input.makeView().readHead()
private fun IoBuffer.readHead(): JceHead {
val var2 = readByte() val var2 = readByte()
val type = var2 and 15 val type = var2 and 15
var tag = (var2.toInt() and 240) shr 4 var tag = (var2.toInt() and 240) shr 4
...@@ -73,6 +88,7 @@ class JceInput( ...@@ -73,6 +88,7 @@ class JceInput(
12 -> 0 12 -> 0
0 -> input.readByte().toLong() 0 -> input.readByte().toLong()
1 -> input.readShort().toLong() 1 -> input.readShort().toLong()
2 -> input.readInt().toLong()
3 -> input.readLong() 3 -> input.readLong()
else -> error("type mismatch: ${it.type}") else -> error("type mismatch: ${it.type}")
} }
...@@ -130,7 +146,7 @@ class JceInput( ...@@ -130,7 +146,7 @@ class JceInput(
13 -> { 13 -> {
val head = readHead() val head = readHead()
check(head.type.toInt() == 0) { "type mismatch" } check(head.type.toInt() == 0) { "type mismatch" }
input.readBytes(input.readInt()) input.readBytes(readInt(0))
} }
else -> error("type mismatch") else -> error("type mismatch")
} }
...@@ -193,11 +209,11 @@ class JceInput( ...@@ -193,11 +209,11 @@ class JceInput(
} }
fun <K, V> readMapOrNull(defaultKey: K, defaultValue: V, tag: Int): Map<K, V>? = skipToTagOrNull(tag) { fun <K, V> readMapOrNull(defaultKey: K, defaultValue: V, tag: Int): Map<K, V>? = skipToTagOrNull(tag) {
check(it.type.toInt() == 8) { "type mismatch" } check(it.type.toInt() == 8) { "type mismatch: ${it.type}" }
val size = readInt(0) val size = readInt(0)
val map = HashMap<K, V>(size) val map = HashMap<K, V>(size)
repeat(size) { repeat(size) {
map[readObject(defaultKey, 0)] = readObject(defaultValue, 0) map[readObject(defaultKey, 0)] = readObject(defaultValue, 1)
} }
return map return map
} }
...@@ -207,7 +223,7 @@ class JceInput( ...@@ -207,7 +223,7 @@ class JceInput(
val size = readInt(0) val size = readInt(0)
val map = HashMap<K, V>(size) val map = HashMap<K, V>(size)
repeat(size) { repeat(size) {
map[readSimpleObject(0)] = readSimpleObject(0) map[readSimpleObject(0)] = readSimpleObject(1)
} }
return map return map
} }
...@@ -223,7 +239,7 @@ class JceInput( ...@@ -223,7 +239,7 @@ class JceInput(
} }
fun <J : JceStruct> readJceStructOrNull(factory: JceStruct.Factory<J>, tag: Int): J? = skipToTagOrNull(tag) { head -> fun <J : JceStruct> readJceStructOrNull(factory: JceStruct.Factory<J>, tag: Int): J? = skipToTagOrNull(tag) { head ->
readHead() check(head.type.toInt() == 10) { "type mismatch" }
return factory.newInstanceFrom(this).also { skipToStructEnd() } return factory.newInstanceFrom(this).also { skipToStructEnd() }
} }
...@@ -333,7 +349,7 @@ class JceInput( ...@@ -333,7 +349,7 @@ class JceInput(
check(head.type.toInt() == 0) { "skipField with invalid type, type value: " + type + ", " + head.type } check(head.type.toInt() == 0) { "skipField with invalid type, type value: " + type + ", " + head.type }
this.input.discardExact(this.readInt(0)) this.input.discardExact(this.readInt(0))
} }
else -> error("invalid type.") else -> error("invalid type: $type")
} }
} }
...@@ -347,7 +363,11 @@ internal inline fun <R> JceInput.skipToTagOrNull(tag: Int, block: (JceHead) -> R ...@@ -347,7 +363,11 @@ internal inline fun <R> JceInput.skipToTagOrNull(tag: Int, block: (JceHead) -> R
if (this.input.endOfInput) if (this.input.endOfInput)
return null return null
val head = readHead() val head = peakHead()
if (head.tag > tag) {
return null
}
readHead()
if (head.tag == tag) { if (head.tag == tag) {
return block(head) return block(head)
} }
......
...@@ -177,7 +177,7 @@ class JceOutput( ...@@ -177,7 +177,7 @@ class JceOutput(
writeInt(map.size, 0) writeInt(map.size, 0)
map.forEach { (key, value) -> map.forEach { (key, value) ->
writeObject(key, 0) writeObject(key, 0)
writeObject(value, 0) writeObject(value, 1)
} }
} }
} }
...@@ -274,7 +274,7 @@ class JceOutput( ...@@ -274,7 +274,7 @@ class JceOutput(
@PublishedApi @PublishedApi
internal fun writeHead(type: Int, tag: Int) { internal fun writeHead(type: Int, tag: Int) {
if (tag < 15) { if (tag < 15) {
this.output.writeByte((tag shl 4 or type).toByte()) this.output.writeByte(((tag shl 4) or type).toByte())
return return
} }
if (tag < 256) { if (tag < 256) {
......
...@@ -11,7 +11,7 @@ class RequestPacket() : JceStruct() { ...@@ -11,7 +11,7 @@ class RequestPacket() : JceStruct() {
var cPacketType: Byte = 0 var cPacketType: Byte = 0
var iMessageType: Int = 0 var iMessageType: Int = 0
var iRequestId: Int = 0 var iRequestId: Int = 0
var iTimeout: Int = 3000 var iTimeout: Int = 0
var iVersion: Short = 3 var iVersion: Short = 3
var context: Map<String, String> = EMPTY_MAP var context: Map<String, String> = EMPTY_MAP
var sFuncName: String = "" var sFuncName: String = ""
...@@ -23,7 +23,7 @@ class RequestPacket() : JceStruct() { ...@@ -23,7 +23,7 @@ class RequestPacket() : JceStruct() {
cPacketType: Byte = 0, cPacketType: Byte = 0,
iMessageType: Int = 0, iMessageType: Int = 0,
iRequestId: Int = 0, iRequestId: Int = 0,
iTimeout: Int = 3000, iTimeout: Int = 0,
iVersion: Short = 3, iVersion: Short = 3,
context: Map<String, String> = EMPTY_MAP, context: Map<String, String> = EMPTY_MAP,
sFuncName: String = "", sFuncName: String = "",
......
...@@ -5,46 +5,84 @@ import net.mamoe.mirai.qqandroid.network.io.JceOutput ...@@ -5,46 +5,84 @@ import net.mamoe.mirai.qqandroid.network.io.JceOutput
import net.mamoe.mirai.qqandroid.network.io.JceStruct import net.mamoe.mirai.qqandroid.network.io.JceStruct
class SvcReqRegister( class SvcReqRegister(
val bIsOnline: Byte = 0, var bIsOnline: Byte = 0,
val bIsSetStatus: Byte = 0, var bIsSetStatus: Byte = 0,
val bIsShowOnline: Byte = 0, var bIsShowOnline: Byte = 0,
val bKikPC: Byte = 0, var bKikPC: Byte = 0,
val bKikWeak: Byte = 0, var bKikWeak: Byte = 0,
val bOnlinePush: Byte = 0, var bOnlinePush: Byte = 0,
val bOpenPush: Byte = 1, var bOpenPush: Byte = 1,
val bRegType: Byte = 0, var bRegType: Byte = 0,
val bSetMute: Byte = 0, var bSetMute: Byte = 0,
val bSlientPush: Byte = 0, var bSlientPush: Byte = 0,
val bytes_0x769_reqbody: ByteArray? = null, var bytes_0x769_reqbody: ByteArray? = null,
val cConnType: Byte = 0, var cConnType: Byte = 0,
val cNetType: Byte = 0, var cNetType: Byte = 0,
val iLargeSeq: Long = 0L, var iLargeSeq: Long = 0L,
val iLastWatchStartTime: Long = 0L, var iLastWatchStartTime: Long = 0L,
val iLocaleID: Int = 2052, var iLocaleID: Int = 2052,
val iOSVersion: Long = 0L, var iOSVersion: Long = 0L,
val iStatus: Int = 11, var iStatus: Int = 11,
val lBid: Long = 0L, var lBid: Long = 0L,
val lCpId: Long = 0L, var lCpId: Long = 0L,
val lUin: Long = 0L, var lUin: Long = 0L,
val sBuildVer: String? = null, var sBuildVer: String? = null,
val sChannelNo: String? = null, var sChannelNo: String? = null,
val sOther: String = "", var sOther: String = "",
val strDevName: String? = null, var strDevName: String? = null,
val strDevType: String? = null, var strDevType: String? = null,
val strIOSIdfa: String? = null, var strIOSIdfa: String? = null,
val strOSVer: String? = null, var strOSVer: String? = null,
val strVendorName: String? = null, var strVendorName: String? = null,
val strVendorOSName: String? = null, var strVendorOSName: String? = null,
val timeStamp: Long = 0L, var timeStamp: Long = 0L,
val uNewSSOIp: Long = 0L, var uNewSSOIp: Long = 0L,
val uOldSSOIp: Long = 0L, var uOldSSOIp: Long = 0L,
val vecDevParam: ByteArray? = null, var vecDevParam: ByteArray? = null,
val vecGuid: ByteArray? = null, var vecGuid: ByteArray? = null,
val vecServerBuf: ByteArray? = null var vecServerBuf: ByteArray? = null,
var vecBindUin: ArrayList<*>? = null // ?? 未知泛型
) : JceStruct() { ) : JceStruct() {
companion object : Factory<RequestPacket> { constructor() : this(0)
override fun newInstanceFrom(input: JceInput): RequestPacket { companion object : Factory<SvcReqRegister> {
TODO("not implemented") override fun newInstanceFrom(input: JceInput): SvcReqRegister = SvcReqRegister().apply {
this.lUin = input.readLong(0)
this.lBid = input.readLong(1)
this.cConnType = input.readByte(2)
this.sOther = input.readString(3)
this.iStatus = input.readInt(4)
this.bOnlinePush = input.readByte(5)
this.bIsOnline = input.readByte(6)
this.bIsShowOnline = input.readByte(7)
this.bKikPC = input.readByte(8)
this.bKikWeak = input.readByte(9)
this.timeStamp = input.readLong(10)
this.iOSVersion = input.readLong(11)
this.cNetType = input.readByte(12)
this.sBuildVer = input.readString(13)
this.bRegType = input.readByte(14)
this.vecDevParam = input.readByteArrayOrNull(15)
this.vecGuid = input.readByteArrayOrNull(16)
this.iLocaleID = input.readIntOrNull(17) ?: this.iLocaleID
this.bSlientPush = input.readByteOrNull(18) ?: this.bSlientPush
this.strDevName = input.readStringOrNull(19) ?: this.strDevName
this.strDevType = input.readStringOrNull(20) ?: this.strDevType
this.strOSVer = input.readStringOrNull(21) ?: this.strOSVer
this.bOpenPush = input.readByteOrNull(22) ?: this.bOpenPush
this.iLargeSeq = input.readLongOrNull(23) ?: this.iLargeSeq
this.iLastWatchStartTime = input.readLongOrNull(24) ?: this.iLastWatchStartTime
// this.vecBindUin = input.readObject(this.vecBindUin, 25) ?: this.iLocaleID
this.uOldSSOIp = input.readLongOrNull(26) ?: this.uOldSSOIp
this.uNewSSOIp = input.readLongOrNull(27) ?: this.uNewSSOIp
this.sChannelNo = input.readStringOrNull(28) ?: this.sChannelNo
this.lCpId = input.readLongOrNull(29) ?: this.lCpId
this.strVendorName = input.readStringOrNull(30) ?: this.strVendorName
this.strVendorOSName = input.readStringOrNull(31) ?: this.strVendorOSName
this.strIOSIdfa = input.readStringOrNull(32) ?: this.strIOSIdfa
this.bytes_0x769_reqbody = input.readByteArrayOrNull(33) ?: this.bytes_0x769_reqbody
this.bIsSetStatus = input.readByteOrNull(34) ?: this.bIsSetStatus
this.vecServerBuf = input.readByteArrayOrNull(35) ?: this.vecServerBuf
this.bSetMute = input.readByteOrNull(36) ?: this.bSetMute
} }
} }
...@@ -63,65 +101,65 @@ class SvcReqRegister( ...@@ -63,65 +101,65 @@ class SvcReqRegister(
builder.write(iOSVersion, 11) builder.write(iOSVersion, 11)
builder.write(cNetType, 12) builder.write(cNetType, 12)
if (sBuildVer != null) { if (sBuildVer != null) {
builder.write(sBuildVer, 13) builder.write(sBuildVer!!, 13)
} }
builder.write(bRegType, 14) builder.write(bRegType, 14)
if (vecDevParam != null) { if (vecDevParam != null) {
builder.write(vecDevParam, 15) builder.write(vecDevParam!!, 15)
} }
if (vecGuid != null) { if (vecGuid != null) {
builder.write(vecGuid, 16) builder.write(vecGuid!!, 16)
} }
builder.write(iLocaleID, 17) builder.write(iLocaleID, 17)
builder.write(bSlientPush, 18) builder.write(bSlientPush, 18)
if (strDevName != null) { if (strDevName != null) {
builder.write(strDevName, 19) builder.write(strDevName!!, 19)
} }
if (strDevType != null) { if (strDevType != null) {
builder.write(strDevType, 20) builder.write(strDevType!!, 20)
} }
if (strOSVer != null) { if (strOSVer != null) {
builder.write(strOSVer, 21) builder.write(strOSVer!!, 21)
} }
builder.write(bOpenPush, 22) builder.write(bOpenPush, 22)
builder.write(iLargeSeq, 23) builder.write(iLargeSeq, 23)
builder.write(iLastWatchStartTime, 24) builder.write(iLastWatchStartTime, 24)
// if (this.vecBindUin != null) { if (this.vecBindUin != null) {
// builder.write(this.vecBindUin, 25) builder.write(this.vecBindUin!!, 25)
// } }
builder.write(uOldSSOIp, 26) builder.write(uOldSSOIp, 26)
builder.write(uNewSSOIp, 27) builder.write(uNewSSOIp, 27)
if (sChannelNo != null) { if (sChannelNo != null) {
builder.write(sChannelNo, 28) builder.write(sChannelNo!!, 28)
} }
builder.write(lCpId, 29) builder.write(lCpId, 29)
if (strVendorName != null) { if (strVendorName != null) {
builder.write(strVendorName, 30) builder.write(strVendorName!!, 30)
} }
if (strVendorOSName != null) { if (strVendorOSName != null) {
builder.write(strVendorOSName, 31) builder.write(strVendorOSName!!, 31)
} }
if (strIOSIdfa != null) { if (strIOSIdfa != null) {
builder.write(strIOSIdfa, 32) builder.write(strIOSIdfa!!, 32)
} }
if (bytes_0x769_reqbody != null) { if (bytes_0x769_reqbody != null) {
builder.write(bytes_0x769_reqbody, 33) builder.write(bytes_0x769_reqbody!!, 33)
} }
builder.write(bIsSetStatus, 34) builder.write(bIsSetStatus, 34)
if (vecServerBuf != null) { if (vecServerBuf != null) {
builder.write(vecServerBuf, 35) builder.write(vecServerBuf!!, 35)
} }
builder.write(bSetMute, 36) builder.write(bSetMute, 36)
......
package net.mamoe.mirai.qqandroid.network.protocol.packet.login package net.mamoe.mirai.qqandroid.network.protocol.packet.login
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.readBytes
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
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.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.io.buildJcePacket
import net.mamoe.mirai.qqandroid.network.io.jceMap import net.mamoe.mirai.qqandroid.network.io.jceMap
import net.mamoe.mirai.qqandroid.network.io.jceStruct import net.mamoe.mirai.qqandroid.network.io.jceStruct
import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
...@@ -16,8 +18,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x76 ...@@ -16,8 +18,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x76
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeLoginSsoPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.writeLoginSsoPacket
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.encodeToString import net.mamoe.mirai.utils.io.encodeToString
import net.mamoe.mirai.utils.io.toReadPacket import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.localIpAddress
@Suppress("EnumEntryName") @Suppress("EnumEntryName")
enum class RegPushReason { enum class RegPushReason {
...@@ -44,7 +48,7 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon ...@@ -44,7 +48,7 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
operator fun invoke( operator fun invoke(
client: QQAndroidClient, client: QQAndroidClient,
regPushReason: RegPushReason = RegPushReason.setOnlineStatus regPushReason: RegPushReason = RegPushReason.appRegister
): OutgoingPacket = buildLoginOutgoingPacket( ): OutgoingPacket = buildLoginOutgoingPacket(
client, client,
bodyType = 1, bodyType = 1,
...@@ -60,57 +64,67 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon ...@@ -60,57 +64,67 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
sFuncName = "SvcReqRegister" sFuncName = "SvcReqRegister"
sBuffer = jceMap( sBuffer = jceMap(
0, 0,
"SvcReqRegister" to jceStruct( "SvcReqRegister" to buildJcePacket {
0, writeObject(jceStruct(
SvcReqRegister( 0,
cConnType = 0, SvcReqRegister(
lBid = 1 or 2 or 4, cConnType = 0,
lUin = client.uin, lBid = 1 or 2 or 4,
iStatus = client.onlineStatus.id, lUin = client.uin,
bKikPC = 0, // 是否把 PC 踢下线 iStatus = client.onlineStatus.id,
bKikWeak = 0, bKikPC = 0, // 是否把 PC 踢下线
timeStamp = currentTimeSeconds, // millis or seconds?? bKikWeak = 0,
iLargeSeq = 0, timeStamp = currentTimeSeconds, // millis or seconds??
bRegType = iLargeSeq = 0,
(if (regPushReason == RegPushReason.appRegister || bOpenPush = 1,
regPushReason == RegPushReason.fillRegProxy || bRegType =
regPushReason == RegPushReason.createDefaultRegInfo || (if (regPushReason == RegPushReason.appRegister ||
regPushReason == RegPushReason.setOnlineStatus regPushReason == RegPushReason.fillRegProxy ||
) 0 else 1).toByte(), regPushReason == RegPushReason.createDefaultRegInfo ||
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0, regPushReason == RegPushReason.setOnlineStatus
iOSVersion = client.device.version.sdk.toLong(), ) 0 else 1).toByte(),
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0, bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0,
vecGuid = client.device.guid, iOSVersion = client.device.version.sdk.toLong(),
strDevName = client.device.model.encodeToString(), cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0,
strDevType = client.device.model.encodeToString(), vecGuid = client.device.guid,
strOSVer = client.device.version.release.encodeToString(), strDevName = client.device.model.encodeToString(),
strDevType = client.device.model.encodeToString(),
strOSVer = client.device.version.release.encodeToString(),
// register 时还需要 uOldSSOIp = 0,
/* uNewSSOIp = localIpAddress().split(".").foldIndexed(0L) { index: Int, acc: Long, s: String ->
var44.uNewSSOIp = field_127445; acc or ((s.toLong() shl (index * 16)))
var44.uOldSSOIp = field_127444; },
var44.strVendorName = ROMUtil.getRomName(); strVendorName = "MIUI",
var44.strVendorOSName = ROMUtil.getRomVersion(20); strVendorOSName = "",
*/ // register 时还需要
bytes_0x769_reqbody = ProtoBuf.dump( /*
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody( var44.uNewSSOIp = field_127445;
rpt_config_list = listOf( var44.uOldSSOIp = field_127444;
Oidb0x769.ConfigSeq( var44.strVendorName = ROMUtil.getRomName();
type = 46, var44.strVendorOSName = ROMUtil.getRomVersion(20);
version = 4 */
), bytes_0x769_reqbody = ProtoBuf.dump(
Oidb0x769.ConfigSeq( Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
type = 283, rpt_config_list = listOf(
version = 0 Oidb0x769.ConfigSeq(
type = 46,
version = 4
),
Oidb0x769.ConfigSeq(
type = 283,
version = 0
)
) )
) )
) ),
), bSetMute = 0
bSetMute = 0 )
) ), 0)
) }.readBytes()
) )
} }
this.writePacket(this.build().debugPrint("sso body"))
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment