mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-08 17:20:11 +08:00
Fix friendlist
This commit is contained in:
parent
bfcd265016
commit
0c6526afb8
@ -29,6 +29,7 @@ import net.mamoe.mirai.utils.io.*
|
||||
import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.jvm.Volatile
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
@ -123,7 +124,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
val data = FriendList.GetFriendGroupList(
|
||||
bot.client,
|
||||
currentFriendCount,
|
||||
20,
|
||||
150,
|
||||
0,
|
||||
0
|
||||
).sendAndExpect<FriendList.GetFriendGroupList.Response>(timeoutMillis = 1000)
|
||||
@ -161,6 +162,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
/**
|
||||
* 缓存超时处理的 [Job]. 超时后将清空缓存, 以免阻碍后续包的处理
|
||||
*/
|
||||
@Volatile
|
||||
private var cachedPacketTimeoutJob: Job? = null
|
||||
/**
|
||||
* 缓存的包
|
||||
@ -169,6 +171,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
/**
|
||||
* 缓存的包还差多少长度
|
||||
*/
|
||||
@Volatile
|
||||
private var expectingRemainingLength: Long = 0
|
||||
|
||||
/**
|
||||
@ -256,8 +259,11 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
if (cache == null) {
|
||||
// 没有缓存
|
||||
var length: Int = rawInput.readInt() - 4
|
||||
if (length < 0) {
|
||||
if (length and 0xFFFF != length) {
|
||||
cachedPacket.value = rawInput
|
||||
expectingRemainingLength = length.toLong() and 0xFFFF
|
||||
// 丢包了. 后半部分包提前到达
|
||||
PacketLogger.error { "丢包了." }
|
||||
return
|
||||
}
|
||||
if (rawInput.remaining == length.toLong()) {
|
||||
@ -267,7 +273,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
return
|
||||
}
|
||||
// 循环所有完整的包
|
||||
while (rawInput.remaining > length) {
|
||||
while (rawInput.remaining >= length) {
|
||||
parsePacketAsync(rawInput.readPacket(length))
|
||||
|
||||
length = rawInput.readInt() - 4
|
||||
@ -284,20 +290,27 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
}
|
||||
} else {
|
||||
// 有缓存
|
||||
|
||||
if (rawInput.remaining >= expectingRemainingLength) {
|
||||
val expectingLength = expectingRemainingLength
|
||||
if (expectingLength and 0xFFFF != expectingLength) {
|
||||
processPacket(buildPacket {
|
||||
writePacket(rawInput)
|
||||
writeInt(expectingLength.toInt())
|
||||
writePacket(cache)
|
||||
})
|
||||
}
|
||||
if (rawInput.remaining >= expectingLength) {
|
||||
// 剩余长度够, 连接上去, 处理这个包.
|
||||
parsePacketAsync(buildPacket {
|
||||
writePacket(cache)
|
||||
writePacket(rawInput, expectingRemainingLength)
|
||||
writePacket(rawInput, expectingLength)
|
||||
})
|
||||
cachedPacket.value = null // 缺少的长度已经给上了.
|
||||
cachedPacketTimeoutJob?.cancel()
|
||||
|
||||
if (rawInput.remaining != 0L) {
|
||||
return processPacket(rawInput) // 继续处理剩下内容
|
||||
} else {
|
||||
// 处理好了.
|
||||
cachedPacketTimeoutJob?.cancel()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
|
@ -11,13 +11,15 @@ class SyncCookie(
|
||||
@SerialId(2) val time: Long, // 1580277992
|
||||
@SerialId(3) val unknown1: Long = Random.nextLong(),// 678328038
|
||||
@SerialId(4) val unknown2: Long = Random.nextLong(), // 1687142153
|
||||
@SerialId(5) val const1: Long = Random.nextLong(), // 1458467940
|
||||
@SerialId(11) val const2: Long = Random.nextLong(), // 2683038258
|
||||
@SerialId(5) val const1: Long = const1_, // 1458467940
|
||||
@SerialId(11) val const2: Long = const2_, // 2683038258
|
||||
@SerialId(12) val unknown3: Long = 0x1d,
|
||||
@SerialId(13) val lastSyncTime: Long? = null,
|
||||
@SerialId(14) val unknown4: Long = 0
|
||||
) : ProtoBuf
|
||||
|
||||
private val const1_: Long = Random.nextLong()
|
||||
private val const2_: Long = Random.nextLong()
|
||||
/*
|
||||
|
||||
@Serializable
|
||||
|
@ -147,6 +147,7 @@ internal object KnownPacketFactories {
|
||||
// login
|
||||
val flag1 = readInt()
|
||||
|
||||
PacketLogger.verbose("开始处理一个包")
|
||||
PacketLogger.verbose("flag1(0A/0B) = ${flag1.toUByte().toUHexString()}")
|
||||
// 00 00 05 30
|
||||
// 00 00 00 0A // flag 1
|
||||
@ -240,10 +241,13 @@ internal object KnownPacketFactories {
|
||||
val ssoSequenceId: Int
|
||||
val dataCompressed: Int
|
||||
// head
|
||||
input.readIoBuffer(input.readInt() - 4).withUse {
|
||||
input.readPacket(input.readInt() - 4).withUse {
|
||||
ssoSequenceId = readInt()
|
||||
PacketLogger.verbose("sequenceId = $ssoSequenceId")
|
||||
check(readInt() == 0)
|
||||
val returnCode = readInt()
|
||||
if (returnCode != 0) {
|
||||
error("returnCode = $returnCode")
|
||||
}
|
||||
val extraData = readBytes(readInt() - 4)
|
||||
PacketLogger.verbose("(sso/inner)extraData = ${extraData.toUHexString()}")
|
||||
|
||||
@ -280,7 +284,7 @@ internal object KnownPacketFactories {
|
||||
ssoSequenceId: Int,
|
||||
consumer: PacketConsumer<T>
|
||||
) {
|
||||
readIoBuffer(readInt() - 4).withUse {
|
||||
readPacket(readInt() - 4).withUse {
|
||||
check(readByte().toInt() == 2)
|
||||
this.discardExact(2) // 27 + 2 + body.size
|
||||
this.discardExact(2) // const, =8001
|
||||
@ -292,30 +296,30 @@ internal object KnownPacketFactories {
|
||||
this.discardExact(1) // const = 0
|
||||
val packet = when (encryptionMethod) {
|
||||
4 -> { // peer public key, ECDH
|
||||
var data = this.decryptBy(bot.client.ecdh.keyPair.initialShareKey, this.readRemaining - 1)
|
||||
var data = this.decryptBy(bot.client.ecdh.keyPair.initialShareKey, (this.remaining - 1).toInt())
|
||||
|
||||
val peerShareKey = bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey())
|
||||
data = data.decryptBy(peerShareKey)
|
||||
|
||||
packetFactory.decode(bot, data.toReadPacket())
|
||||
packetFactory.decode(bot, data)
|
||||
}
|
||||
0 -> {
|
||||
val data = if (bot.client.loginState == 0) {
|
||||
ByteArrayPool.useInstance { byteArrayBuffer ->
|
||||
val size = this.readRemaining - 1
|
||||
val size = (this.remaining - 1).toInt()
|
||||
this.readFully(byteArrayBuffer, 0, size)
|
||||
|
||||
runCatching {
|
||||
byteArrayBuffer.decryptBy(bot.client.ecdh.keyPair.initialShareKey, size)
|
||||
}.getOrElse {
|
||||
byteArrayBuffer.decryptBy(bot.client.randomKey, size)
|
||||
} // 这里实际上应该用 privateKey(另一个random出来的key)
|
||||
}.toReadPacket() // 这里实际上应该用 privateKey(另一个random出来的key)
|
||||
}
|
||||
} else {
|
||||
this.decryptBy(bot.client.randomKey, 0, this.readRemaining - 1)
|
||||
this.decryptBy(bot.client.randomKey, 0, (this.remaining - 1).toInt())
|
||||
}
|
||||
|
||||
packetFactory.decode(bot, data.toReadPacket())
|
||||
packetFactory.decode(bot, data)
|
||||
|
||||
}
|
||||
else -> error("Illegal encryption method. expected 0 or 4, got $encryptionMethod")
|
||||
@ -337,4 +341,16 @@ internal inline fun <I : IoBuffer, R> I.withUse(block: I.() -> R): R {
|
||||
} finally {
|
||||
this.release(IoBuffer.Pool)
|
||||
}
|
||||
}
|
||||
|
||||
@UseExperimental(ExperimentalContracts::class)
|
||||
internal inline fun <I : ByteReadPacket, R> I.withUse(block: I.() -> R): R {
|
||||
contract {
|
||||
callsInPlace(block, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return try {
|
||||
block(this)
|
||||
} finally {
|
||||
this.close()
|
||||
}
|
||||
}
|
@ -19,7 +19,10 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.SyncCookie
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.qqandroid.utils.toMessageChain
|
||||
import net.mamoe.mirai.qqandroid.utils.toRichTextElems
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
@ -229,7 +232,7 @@ internal class MessageSvc {
|
||||
),
|
||||
msgSeq = client.atomicNextMessageSequenceId(),
|
||||
//msgRand = Random.nextInt() and 0x7FFF,
|
||||
syncCookie = client.c2cMessageSync.syncCookie?.takeIf { it.isNotEmpty() } ?: EMPTY_BYTE_ARRAY
|
||||
syncCookie = SyncCookie(time = currentTimeSeconds).toByteArray(SyncCookie.serializer())
|
||||
//SyncCookie(currentTimeSeconds, Random.nextLong().absoluteValue, Random.nextLong().absoluteValue).toByteArray(SyncCookie.serializer())
|
||||
// msgVia = 1
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
|
||||
import net.mamoe.mirai.utils.io.discardExact
|
||||
import net.mamoe.mirai.utils.io.debugIfFail
|
||||
|
||||
|
||||
internal class FriendList {
|
||||
@ -120,8 +120,8 @@ internal class FriendList {
|
||||
}
|
||||
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
|
||||
this.discardExact(4)
|
||||
val res = this.decodeUniPacket(GetFriendListResp.serializer())
|
||||
//this.discardExact(4)
|
||||
val res = this.debugIfFail { this.decodeUniPacket(GetFriendListResp.serializer()) }
|
||||
return Response(
|
||||
res.totoalFriendCount,
|
||||
res.vecFriendInfo.orEmpty()
|
||||
|
@ -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 = 8192
|
||||
internal const val DEFAULT_BYTE_ARRAY_SIZE = 81920
|
||||
|
||||
val ByteArrayPool: ObjectPool<ByteArray> = ByteArrayPoolImpl
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user