فهرست منبع

Rework seq system (#1230)

* Rework seq system, should help #1209

* Use non-blocking (CAS) implement

* Making next seq code more clear for reading

* Fix mistake
sandtechnology 4 سال پیش
والد
کامیت
db4c41f84a

+ 6 - 0
mirai-core-utils/src/commonMain/kotlin/RandomUtils.kt

@@ -14,6 +14,7 @@
 package net.mamoe.mirai.utils
 
 
+import kotlin.math.absoluteValue
 import kotlin.random.Random
 import kotlin.random.nextInt
 
@@ -23,6 +24,11 @@ import kotlin.random.nextInt
  */
 public fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() }
 
+/**
+ * 随机生成一个正整数
+ */
+public fun getRandomUnsignedInt(): Int = Random.nextInt().absoluteValue
+
 /**
  * 随机生成长度为 [length] 的 [String].
  */

+ 28 - 26
mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt

@@ -86,48 +86,50 @@ internal open class QQAndroidClient(
     internal val miscBitMap: Int get() = protocol.miscBitMap // 184024956 // 也可能是 150470524 ?
     internal val mainSigMap: Int get() = protocol.mainSigMap
 
-    private val _ssoSequenceId: AtomicInt = atomic(85600)
+    @Volatile
+    private var _ssoSequenceId: Int = Random.nextInt(100000)
 
     var fileStoragePushFSSvcList: FileStoragePushFSSvcList? = null
 
+    @Synchronized
     @MiraiInternalApi("Do not use directly. Get from the lambda param of buildSsoPacket")
-    internal fun nextSsoSequenceId() = _ssoSequenceId.addAndGet(2)
+    internal fun nextSsoSequenceId(): Int {
+        _ssoSequenceId += 2
+        val new = _ssoSequenceId
+        if (new > 100000) {
+            _ssoSequenceId = Random.nextInt(100000) + 60000
+        }
+        return new
+    }
 
 
     val apkVersionName: ByteArray get() = protocol.ver.toByteArray() //"8.4.18".toByteArray()
     val buildVer: String get() = "8.4.18.4810" // 8.2.0.1296 // 8.4.8.4810 // 8.2.7.4410
 
 
-    private val messageSequenceId: AtomicInt = atomic(22911)
-    internal fun atomicNextMessageSequenceId(): Int = messageSequenceId.getAndAdd(2)
-
-
-    private val friendSeq: AtomicInt = atomic(22911)
-    internal fun getFriendSeq(): Int {
-        return friendSeq.value
-    }
+    private val sequenceId: AtomicInt = atomic(getRandomUnsignedInt())
+    internal fun atomicNextMessageSequenceId(): Int = sequenceId.incrementAndGet()
+    internal fun nextRequestPacketRequestId(): Int = sequenceId.incrementAndGet()
 
-    internal fun nextFriendSeq(): Int {
-        return friendSeq.incrementAndGet()
-    }
+    @Volatile
+    private var highwayDataTransSequenceId: Int = Random.nextInt(100000)
 
-    internal fun setFriendSeq(compare: Int, id: Int): Boolean {
-        return friendSeq.compareAndSet(compare, id % 65535)
+    @Synchronized
+    internal fun nextHighwayDataTransSequenceId(): Int {
+        highwayDataTransSequenceId += 1
+        val new = highwayDataTransSequenceId
+        if (new > 1000000) {
+            highwayDataTransSequenceId = Random.nextInt(1060000)
+        }
+        return new
     }
 
+    private val friendSeq: AtomicInt = atomic(getRandomUnsignedInt())
+    internal fun getFriendSeq(): Int = friendSeq.value
 
-    private val requestPacketRequestId: AtomicInt = atomic(1921334513)
-    internal fun nextRequestPacketRequestId(): Int = requestPacketRequestId.getAndAdd(2)
-
-    private val highwayDataTransSequenceIdForGroup: AtomicInt = atomic(87017)
-    internal fun nextHighwayDataTransSequenceIdForGroup(): Int = highwayDataTransSequenceIdForGroup.getAndAdd(2)
-
-    private val highwayDataTransSequenceIdForFriend: AtomicInt = atomic(43973)
-    internal fun nextHighwayDataTransSequenceIdForFriend(): Int = highwayDataTransSequenceIdForFriend.getAndAdd(2)
-
-    private val highwayDataTransSequenceIdForApplyUp: AtomicInt = atomic(77918)
-    internal fun nextHighwayDataTransSequenceIdForApplyUp(): Int = highwayDataTransSequenceIdForApplyUp.getAndAdd(2)
+    internal fun nextFriendSeq(): Int = friendSeq.incrementAndGet()
 
+    internal fun setFriendSeq(compare: Int, id: Int): Boolean = friendSeq.compareAndSet(compare, id % 65535)
 
     val appClientVersion: Int = 0
 

+ 1 - 7
mirai-core/src/commonMain/kotlin/network/highway/Highway.kt

@@ -388,13 +388,7 @@ internal fun highwayPacketSession(
                 version = 1,
                 uin = client.uin.toString(),
                 command = command,
-                seq = when (commandId) {
-                    2 -> client.nextHighwayDataTransSequenceIdForGroup()
-                    1 -> client.nextHighwayDataTransSequenceIdForFriend()
-                    27 -> client.nextHighwayDataTransSequenceIdForApplyUp()
-                    29 -> client.nextHighwayDataTransSequenceIdForGroup()
-                    else -> client.nextHighwayDataTransSequenceIdForGroup()
-                },
+                seq = client.nextHighwayDataTransSequenceId(),
                 retryTimes = 0,
                 appid = appId,
                 dataflag = dataFlag,

+ 5 - 4
mirai-core/src/commonMain/kotlin/network/protocol/packet/chat/receive/MessageSvc.PbSendMsg.kt

@@ -35,6 +35,7 @@ import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
 import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
 import net.mamoe.mirai.message.data.*
 import net.mamoe.mirai.utils.currentTimeSeconds
+import net.mamoe.mirai.utils.getRandomUnsignedInt
 import java.util.concurrent.atomic.AtomicReference
 import kotlin.contracts.InvocationKind
 import kotlin.contracts.contract
@@ -116,11 +117,11 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
         else listOf(message)
 
         val response = mutableListOf<OutgoingPacket>()
-        val div = if (fragmented.size == 1) 0 else Random.nextInt().absoluteValue
+        val div = if (fragmented.size == 1) 0 else getRandomUnsignedInt()
         val pkgNum = fragmented.size
 
         val seqIds = sequenceIdsInitializer(pkgNum)
-        val randIds0 = IntArray(pkgNum) { Random.nextInt().absoluteValue }
+        val randIds0 = IntArray(pkgNum) { getRandomUnsignedInt() }
         sequenceIds.set(seqIds)
         randIds.set(randIds0)
         postInit()
@@ -182,7 +183,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
             sequenceIds = sequenceIds,
             randIds = randIds,
             sequenceIdsInitializer = { size ->
-                IntArray(size) { client.nextFriendSeq() }
+                IntArray(size) { client.atomicNextMessageSequenceId() }
             },
             postInit = {
                 source(
@@ -379,7 +380,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
             sequenceIds = sequenceIds,
             randIds = randIds,
             sequenceIdsInitializer = { size ->
-                IntArray(size) { client.nextFriendSeq() }
+                IntArray(size) { client.atomicNextMessageSequenceId() }
             },
             postInit = {
                 randIds.get().forEach { id ->