mirror of
https://github.com/mamoe/mirai.git
synced 2024-12-29 10:00:13 +08:00
[core] Introduce CacheValidator for validating caches (#2388)
* [core] Export DeviceInfo.serializer() to mirai-core * [core] Introduce CacheValidator for validating caches
This commit is contained in:
parent
6365e23f2c
commit
553ea9abbc
@ -118,6 +118,8 @@ public expect class DeviceInfo(
|
||||
*/
|
||||
@JvmStatic
|
||||
public fun random(random: Random): DeviceInfo
|
||||
|
||||
public fun serializer(): KSerializer<DeviceInfo>
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,6 +52,7 @@ import net.mamoe.mirai.internal.network.notice.priv.PrivateMessageProcessor
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
|
||||
import net.mamoe.mirai.internal.utils.ImagePatcher
|
||||
import net.mamoe.mirai.internal.utils.ImagePatcherImpl
|
||||
import net.mamoe.mirai.internal.utils.actualCacheDir
|
||||
import net.mamoe.mirai.internal.utils.subLogger
|
||||
import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
@ -208,6 +209,14 @@ internal open class QQAndroidBot constructor(
|
||||
|
||||
set(SsoProcessorContext, SsoProcessorContextImpl(bot))
|
||||
set(SsoProcessor, SsoProcessorImpl(get(SsoProcessorContext)))
|
||||
|
||||
val cacheValidator = CacheValidatorImpl(
|
||||
get(SsoProcessorContext),
|
||||
configuration.actualCacheDir().resolve("validator.bin"),
|
||||
networkLogger.subLogger("CacheValidator"),
|
||||
)
|
||||
set(CacheValidator, cacheValidator)
|
||||
|
||||
set(HeartbeatProcessor, HeartbeatProcessorImpl())
|
||||
set(HeartbeatScheduler, TimeBasedHeartbeatSchedulerImpl(networkLogger.subLogger("HeartbeatScheduler")))
|
||||
set(HttpClientProvider, HttpClientProviderImpl())
|
||||
@ -251,6 +260,9 @@ internal open class QQAndroidBot constructor(
|
||||
configuration.createAccountsSecretsManager(bot.logger.subLogger("AccountSecretsManager")),
|
||||
)
|
||||
set(ImagePatcher, ImagePatcherImpl())
|
||||
|
||||
cacheValidator.register(get(AccountSecretsManager))
|
||||
cacheValidator.register(get(BdhSessionSyncer))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,10 +35,10 @@ import kotlin.jvm.Volatile
|
||||
* @see FileCacheAccountSecretsManager
|
||||
* @see CombinedAccountSecretsManager
|
||||
*/
|
||||
internal interface AccountSecretsManager {
|
||||
internal interface AccountSecretsManager : Cacheable {
|
||||
fun saveSecrets(account: BotAccount, secrets: AccountSecrets)
|
||||
fun getSecrets(account: BotAccount): AccountSecrets?
|
||||
fun invalidate()
|
||||
override fun invalidate()
|
||||
|
||||
companion object : ComponentKey<AccountSecretsManager>
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import net.mamoe.mirai.internal.utils.actualCacheDir
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.jvm.Volatile
|
||||
|
||||
internal interface BdhSessionSyncer {
|
||||
internal interface BdhSessionSyncer : Cacheable {
|
||||
val bdhSession: CompletableDeferred<BdhSession>
|
||||
val hasSession: Boolean
|
||||
|
||||
@ -77,6 +77,11 @@ internal class BdhSessionSyncerImpl(
|
||||
private val serverListCacheFile: MiraiFile
|
||||
get() = configuration.actualCacheDir().resolve("servers.json")
|
||||
|
||||
override fun invalidate() {
|
||||
sessionCacheFile.delete()
|
||||
serverListCacheFile.delete()
|
||||
}
|
||||
|
||||
override fun loadServerListFromCache() {
|
||||
val serverListCacheFile = this.serverListCacheFile
|
||||
if (serverListCacheFile.isFile) {
|
||||
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2019-2022 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/dev/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.internal.network.components
|
||||
|
||||
import io.ktor.utils.io.core.*
|
||||
import net.mamoe.mirai.internal.network.ProtoBufForCache
|
||||
import net.mamoe.mirai.internal.network.component.ComponentKey
|
||||
import net.mamoe.mirai.internal.utils.MiraiProtocolInternal
|
||||
import net.mamoe.mirai.internal.utils.io.writeShortLVString
|
||||
import net.mamoe.mirai.utils.*
|
||||
|
||||
/**
|
||||
* Validator for checking caches is usable for current bot or not.
|
||||
*/
|
||||
internal interface CacheValidator {
|
||||
fun register(cache: Cacheable)
|
||||
|
||||
fun validate()
|
||||
|
||||
companion object : ComponentKey<CacheValidator>
|
||||
}
|
||||
|
||||
internal interface Cacheable {
|
||||
fun invalidate()
|
||||
}
|
||||
|
||||
internal class CacheValidatorImpl(
|
||||
private val ssoProcessorContext: SsoProcessorContext,
|
||||
private val hashFile: MiraiFile,
|
||||
private val logger: MiraiLogger,
|
||||
) : CacheValidator {
|
||||
private val caches: MutableList<Cacheable> = mutableListOf()
|
||||
|
||||
override fun register(cache: Cacheable) {
|
||||
caches.add(cache)
|
||||
}
|
||||
|
||||
override fun validate() {
|
||||
|
||||
val hash: ByteArray = buildPacket {
|
||||
val botConf = ssoProcessorContext.configuration
|
||||
writeInt(botConf.protocol.ordinal)
|
||||
val internalProtocol = MiraiProtocolInternal[botConf.protocol]
|
||||
writeShortLVString(internalProtocol.apkId)
|
||||
writeLong(internalProtocol.id)
|
||||
writeShortLVString(internalProtocol.sdkVer)
|
||||
writeInt(internalProtocol.miscBitMap)
|
||||
writeInt(internalProtocol.subSigMap)
|
||||
writeInt(internalProtocol.mainSigMap)
|
||||
writeShortLVString(internalProtocol.sign)
|
||||
writeLong(internalProtocol.buildTime)
|
||||
writeInt(internalProtocol.ssoVersion)
|
||||
|
||||
val device = ssoProcessorContext.device
|
||||
|
||||
@Suppress("INVISIBLE_MEMBER")
|
||||
writeFully(ProtoBufForCache.encodeToByteArray(DeviceInfo.serializer(), device))
|
||||
}.let { pkg ->
|
||||
try {
|
||||
pkg.readBytes()
|
||||
} finally {
|
||||
pkg.release()
|
||||
}
|
||||
}.sha1()
|
||||
|
||||
if (!hashFile.exists()) {
|
||||
logger.verbose { "Invalidate caches because hash file not available." }
|
||||
|
||||
invalidate()
|
||||
|
||||
kotlin.runCatching {
|
||||
hashFile.writeBytes(hash)
|
||||
}.onFailure { logger.warning("Exception in writing hash to validation file", it) }
|
||||
return
|
||||
}
|
||||
if (!hashFile.isFile) {
|
||||
logger.verbose { "hash file isn't a file." }
|
||||
invalidate()
|
||||
|
||||
kotlin.runCatching {
|
||||
hashFile.deleteRecursively()
|
||||
hashFile.writeBytes(hash)
|
||||
}.onFailure { logger.warning("Exception in writing hash to validation file", it) }
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val hashInFile = hashFile.readBytes()
|
||||
if (hashInFile.contentEquals(hash)) {
|
||||
logger.verbose { "Validated caches." }
|
||||
return
|
||||
}
|
||||
|
||||
logger.verbose { "Hash not match. Invaliding caches....." }
|
||||
invalidate()
|
||||
|
||||
hashFile.writeBytes(hash)
|
||||
} catch (e: Throwable) {
|
||||
logger.warning("Exception in validation. Invalidating.....", e)
|
||||
invalidate()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun invalidate() {
|
||||
caches.forEach { it.invalidate() }
|
||||
}
|
||||
}
|
@ -146,6 +146,8 @@ internal class SsoProcessorImpl(
|
||||
* Do login. Throws [LoginFailedException] if failed
|
||||
*/
|
||||
override suspend fun login(handler: NetworkHandler) = withExceptionCollector {
|
||||
components[CacheValidator].validate()
|
||||
|
||||
components[BdhSessionSyncer].loadServerListFromCache()
|
||||
try {
|
||||
if (client.wLoginSigInfoInitialized) {
|
||||
|
Loading…
Reference in New Issue
Block a user