Commit eb19f6e4 authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
parents df561360 8eb3daca
...@@ -37,9 +37,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -37,9 +37,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
println("Sending login") println("Sending login")
LoginPacket.SubCommand9(bot.client).sendAndExpect<LoginPacket.LoginPacketResponse>() LoginPacket.SubCommand9(bot.client).sendAndExpect<LoginPacket.LoginPacketResponse>()
println("SessionTicket=${bot.client.wLoginSigInfo.wtSessionTicket.data.toUHexString()}") println("SessionTicket=${bot.client.wLoginSigInfo.wtSessionTicket.data.toUHexString()}")
println("SessionTicketKey=${bot.client.wLoginSigInfo.d2Key.toUHexString()}") println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
println("SessionTicketKey=${bot.client.wLoginSigInfo.wtSessionTicketKey.toUHexString()}") println("SessionTicketKey=${bot.client.wLoginSigInfo.wtSessionTicketKey.toUHexString()}")
delay(2000) delay(2000)
println()
println()
println()
println("Sending ReqRegister")
SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>() SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>()
} }
......
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)
......
...@@ -6,6 +6,7 @@ import kotlinx.io.core.ByteReadPacket ...@@ -6,6 +6,7 @@ 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.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
...@@ -109,11 +110,11 @@ internal inline fun PacketFactory<*>.buildOutgingPacket( ...@@ -109,11 +110,11 @@ internal inline fun PacketFactory<*>.buildOutgingPacket(
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, bodyType: Byte,
extraData: ByteArray = EMPTY_BYTE_ARRAY, extraData: ByteArray = EMPTY_BYTE_ARRAY,
name: String? = null, name: String? = null,
id: PacketId = this.id, id: PacketId = this.id,
ssoExtraData: ByteReadPacket = BRP_STUB, 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()
...@@ -121,7 +122,7 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( ...@@ -121,7 +122,7 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
return OutgoingPacket(name, id, sequenceId, buildPacket { return OutgoingPacket(name, id, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x00_00_00_0A) writeInt(0x00_00_00_0A)
writeByte(0x02) writeByte(bodyType)
extraData.let { extraData.let {
writeInt(it.size + 4) writeInt(it.size + 4)
writeFully(it) writeFully(it)
...@@ -133,10 +134,8 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( ...@@ -133,10 +134,8 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
writeStringUtf8(it) writeStringUtf8(it)
} }
encryptAndWrite(KEY_16_ZEROS) { encryptAndWrite(key) {
writeLoginSsoPacket(client, subAppId, id, ssoExtraData, sequenceId) { body(sequenceId)
body(sequenceId)
}
} }
} }
}) })
...@@ -169,7 +168,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY) ...@@ -169,7 +168,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
* byte[] body() * byte[] body()
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
private inline fun BytePacketBuilder.writeLoginSsoPacket( internal inline fun BytePacketBuilder.writeLoginSsoPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, subAppId: Long,
packetId: PacketId, packetId: PacketId,
......
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
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
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.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgingPacket 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.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.localIpAddress
@Suppress("EnumEntryName") @Suppress("EnumEntryName")
enum class RegPushReason { enum class RegPushReason {
...@@ -34,65 +40,91 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon ...@@ -34,65 +40,91 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
internal object Response : Packet internal object Response : Packet
const val subAppId = 537062845L
init {
_id = PacketId(0, "StatSvc.register")
}
operator fun invoke( operator fun invoke(
client: QQAndroidClient, client: QQAndroidClient,
regPushReason: RegPushReason = RegPushReason.setOnlineStatus regPushReason: RegPushReason = RegPushReason.appRegister
): OutgoingPacket = buildOutgingPacket(client, key = client.wLoginSigInfo.d2Key) { ): OutgoingPacket = buildLoginOutgoingPacket(
writeUniRequestPacket { client,
sServantName = "PushService" bodyType = 1,
sFuncName = "SvcReqRegister" extraData = client.wLoginSigInfo.d2.data,
sBuffer = jceMap( key = client.wLoginSigInfo.d2Key
0, ) { sequenceId ->
"SvcReqRegister" to jceStruct( writeLoginSsoPacket(
client, subAppId = subAppId, packetId = id,
extraData = client.wLoginSigInfo.tgt.toReadPacket(), sequenceId = sequenceId
) {
writeUniRequestPacket {
sServantName = "PushService"
sFuncName = "SvcReqRegister"
sBuffer = jceMap(
0, 0,
SvcReqRegister( "SvcReqRegister" to buildJcePacket {
cConnType = 0, writeObject(jceStruct(
lBid = 1 or 2 or 4, 0,
lUin = client.uin, SvcReqRegister(
iStatus = client.onlineStatus.id, cConnType = 0,
bKikPC = 0, // 是否把 PC 踢下线 lBid = 1 or 2 or 4,
bKikWeak = 0, lUin = client.uin,
timeStamp = currentTimeSeconds, // millis or seconds?? iStatus = client.onlineStatus.id,
iLargeSeq = 0, bKikPC = 0, // 是否把 PC 踢下线
bRegType = bKikWeak = 0,
(if (regPushReason == RegPushReason.appRegister || timeStamp = currentTimeSeconds, // millis or seconds??
regPushReason == RegPushReason.fillRegProxy || iLargeSeq = 0,
regPushReason == RegPushReason.createDefaultRegInfo || bOpenPush = 1,
regPushReason == RegPushReason.setOnlineStatus bRegType =
) 0 else 1).toByte(), (if (regPushReason == RegPushReason.appRegister ||
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0, regPushReason == RegPushReason.fillRegProxy ||
iOSVersion = client.device.version.sdk.toLong(), regPushReason == RegPushReason.createDefaultRegInfo ||
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0, regPushReason == RegPushReason.setOnlineStatus
vecGuid = client.device.guid, ) 0 else 1).toByte(),
strDevName = client.device.model.encodeToString(), bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0,
strDevType = client.device.model.encodeToString(), iOSVersion = client.device.version.sdk.toLong(),
strOSVer = client.device.version.release.encodeToString(), 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 时还需要 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
) )
), ), 0)
bSetMute = 0 }.readBytes()
)
) )
) }
this.writePacket(this.build().debugPrint("sso body"))
} }
} }
......
...@@ -6,7 +6,6 @@ import net.mamoe.mirai.data.Packet ...@@ -6,7 +6,6 @@ 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.protocol.packet.* import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.utils.io.toReadPacket
internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() { internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
...@@ -20,7 +19,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() { ...@@ -20,7 +19,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
@Suppress("FunctionName") @Suppress("FunctionName")
fun SubCommand1( fun SubCommand1(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, subAppId, ssoExtraData = byteArrayOf().toReadPacket()) { ): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2) {
writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) { writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
// oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody // oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody
......
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