diff --git a/mirai-core-api/src/commonMain/kotlin/spi/SPIServiceLoader.kt b/mirai-core-api/src/commonMain/kotlin/spi/SPIServiceLoader.kt index d08ebb01c..e8d4b2bd8 100644 --- a/mirai-core-api/src/commonMain/kotlin/spi/SPIServiceLoader.kt +++ b/mirai-core-api/src/commonMain/kotlin/spi/SPIServiceLoader.kt @@ -41,6 +41,7 @@ internal fun SpiServiceLoader( internal interface SpiServiceLoader { val service: T + val allServices: List } internal class SpiServiceLoaderImpl( @@ -52,9 +53,15 @@ internal class SpiServiceLoaderImpl( } private val lock = SynchronizedObject() - override val service: T get() = _service + override val service: T get() = _service.bestService + override val allServices: List get() = _service.allServices - private var _service: T by lateinitMutableProperty { + private class Loaded( + val bestService: T, + val allServices: List, + ) + + private var _service: Loaded by lateinitMutableProperty { synchronized(lock) { reloadAndSelect() } @@ -66,9 +73,12 @@ internal class SpiServiceLoaderImpl( } } - private fun reloadAndSelect(): T { + private fun reloadAndSelect(): Loaded { + val allServices = loadServices(serviceType).toList() + @Suppress("UNCHECKED_CAST") - return (loadServices(serviceType).minByOrNull { it.priority } ?: defaultInstance) as T + val bestService = (allServices.minByOrNull { it.priority } ?: defaultInstance) as T + return Loaded(bestService, allServices) } companion object { diff --git a/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt b/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt index 71b6e5037..dbb9741fe 100644 --- a/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt +++ b/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt @@ -82,6 +82,10 @@ internal open class QQAndroidClient( override var outgoingPacketSessionId: ByteArray = 0x02B05B8B.toByteArray() override var loginState = 0 + val useAndroid by lazy { + bot.configuration.protocol == BotConfiguration.MiraiProtocol.ANDROID_PHONE || + bot.configuration.protocol == BotConfiguration.MiraiProtocol.ANDROID_PAD + } var onlineStatus: OnlineStatus = OnlineStatus.ONLINE var fileStoragePushFSSvcList: FileStoragePushFSSvcList? = null diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/Tlv.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/Tlv.kt index f7a6e7316..047852b80 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/Tlv.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/Tlv.kt @@ -1,5 +1,5 @@ /* - * Copyright 2019-2022 Mamoe Technologies and contributors. + * Copyright 2019-2023 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. @@ -14,6 +14,8 @@ package net.mamoe.mirai.internal.network.protocol.packet import io.ktor.utils.io.core.* import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.protocol.LoginType +import net.mamoe.mirai.internal.spi.EncryptService +import net.mamoe.mirai.internal.spi.EncryptServiceContext import net.mamoe.mirai.internal.utils.GuidSource import net.mamoe.mirai.internal.utils.MacOrAndroidIdChangeFlag import net.mamoe.mirai.internal.utils.NetworkType @@ -961,10 +963,55 @@ internal fun TlvMapWriter.t548( } } -internal fun TlvMapWriter.t544( // 1334 + +internal fun TlvMapWriter.t544ForToken( // 1348 + uin: Long, + guid: ByteArray, + sdkVersion: String, + subCommandId: Int, + commandStr: String ) { + val service = EncryptService.instance ?: return tlv(0x544) { - writeFully(byteArrayOf(0, 0, 0, 11)) // means native throws exception + buildPacket { + writeFully(buildPacket { + writeLong(uin) + }.readBytes(4)) + writeShortLVByteArray(guid) + writeShortLVString(sdkVersion) + writeInt(subCommandId) + writeInt(0) + }.use { dataIn -> + service.encryptTlv(EncryptServiceContext(uin, buildTypeSafeMap { + set(EncryptServiceContext.KEY_COMMAND_STR, commandStr) + }), 0x544, dataIn.readBytes()) + }.let { result -> + writeFully(result ?: "".toByteArray()) // Empty str means native throws exception + } + } +} + +internal fun TlvMapWriter.t544ForVerify( // 1348 + uin: Long, + guid: ByteArray, + sdkVersion: String, + subCommandId: Int, + commandStr: String +) { + val service = EncryptService.instance ?: return + tlv(0x544) { + buildPacket { + writeLong(uin) + writeShortLVByteArray(guid) + writeShortLVString(sdkVersion) + writeInt(subCommandId) + }.use { dataIn -> + service.encryptTlv(EncryptServiceContext(uin, buildTypeSafeMap { + set(EncryptServiceContext.KEY_COMMAND_STR, commandStr) + }), 0x544, dataIn.readBytes()) + }.let { result -> + writeFully(result ?: "".toByteArray()) // Empty str means native throws exception + } } } diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin10.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin10.kt index e4a07f3b3..fe96fe5ae 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin10.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin10.kt @@ -85,7 +85,15 @@ internal object WtLogin10 : WtLoginExt { t194(client.device.imsiMd5) t511() t202(client.device.wifiBSSID, client.device.wifiSSID) - //t544() + if (client.useAndroid) { + t544ForToken( + uin = client.uin, + guid = client.device.guid, + sdkVersion = client.sdkVersion, + subCommandId = 10, + commandStr = "810_a" + ) + } } } diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin15.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin15.kt index 961372856..13fbeabf9 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin15.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin15.kt @@ -135,7 +135,15 @@ internal object WtLogin15 : WtLoginExt { t521() // new t525(client.loginExtraData) // new - //t544() // new 810_f + if (client.useAndroid) { + t544ForToken( + uin = client.uin, + guid = client.device.guid, + sdkVersion = client.sdkVersion, + subCommandId = 15, + commandStr = "810_f" + ) + } t545(client.qimei16 ?: client.device.imei) } } diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin2.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin2.kt index 762a825c1..7f1de27bf 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin2.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin2.kt @@ -10,12 +10,9 @@ package net.mamoe.mirai.internal.network.protocol.packet.login.wtlogin import io.ktor.utils.io.core.* -import net.mamoe.mirai.internal.network.QQAndroidClient -import net.mamoe.mirai.internal.network.miscBitMap +import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.protocol.packet.* import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin -import net.mamoe.mirai.internal.network.subAppId -import net.mamoe.mirai.internal.network.subSigMap import net.mamoe.mirai.utils._writeTlvMap @@ -34,6 +31,15 @@ internal object WtLogin2 : WtLoginExt { t104(client.t104) t116(client.miscBitMap, client.subSigMap) client.t547?.let { t547(it) } + if (client.useAndroid) { + t544ForVerify( + uin = client.uin, + guid = client.device.guid, + sdkVersion = client.sdkVersion, + subCommandId = 2, + commandStr = "810_2" + ) + } } } } @@ -54,6 +60,15 @@ internal object WtLogin2 : WtLoginExt { t104(client.t104) t116(client.miscBitMap, client.subSigMap) client.t547?.let { t547(it) } + if (client.useAndroid) { + t544ForVerify( + uin = client.uin, + guid = client.device.guid, + sdkVersion = client.sdkVersion, + subCommandId = 2, + commandStr = "810_2" + ) + } } } } diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin7.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin7.kt index 3ae5c433b..a1363079b 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin7.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin7.kt @@ -10,12 +10,9 @@ package net.mamoe.mirai.internal.network.protocol.packet.login.wtlogin import io.ktor.utils.io.core.* -import net.mamoe.mirai.internal.network.QQAndroidClient -import net.mamoe.mirai.internal.network.miscBitMap +import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.protocol.packet.* import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin -import net.mamoe.mirai.internal.network.subAppId -import net.mamoe.mirai.internal.network.subSigMap import net.mamoe.mirai.utils.DeviceVerificationRequests import net.mamoe.mirai.utils._writeTlvMap @@ -44,6 +41,15 @@ internal object WtLogin7 : WtLoginExt { t17c(code.encodeToByteArray()) t401(client.G) t198() + if (client.useAndroid) { + t544ForVerify( + uin = client.uin, + guid = client.device.guid, + sdkVersion = client.sdkVersion, + subCommandId = 7, + commandStr = "810_7" + ) + } } } } diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin9.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin9.kt index 8678df634..736afde76 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin9.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/wtlogin/WtLogin9.kt @@ -134,6 +134,15 @@ internal object WtLogin9 : WtLoginExt { // this.build().debugPrint("傻逼") // ignored t318 because not logging in by QR + if (client.useAndroid) { + t544ForToken( + uin = client.uin, + guid = client.device.guid, + sdkVersion = client.sdkVersion, + subCommandId = 9, + commandStr = "810_9" + ) + } } } } diff --git a/mirai-core/src/commonMain/kotlin/spi/EncryptService.kt b/mirai-core/src/commonMain/kotlin/spi/EncryptService.kt new file mode 100644 index 000000000..62a18c338 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/spi/EncryptService.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2019-2023 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 + */ +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + +package net.mamoe.mirai.internal.spi + +import net.mamoe.mirai.Bot +import net.mamoe.mirai.spi.BaseService +import net.mamoe.mirai.spi.SpiServiceLoader +import net.mamoe.mirai.utils.BotConfiguration +import net.mamoe.mirai.utils.MiraiInternalApi +import net.mamoe.mirai.utils.TypeKey +import net.mamoe.mirai.utils.TypeSafeMap + + +/** + * @since 2.15.0 + */ +public class EncryptServiceContext @MiraiInternalApi constructor( + /** + * [Bot.id] + */ + public val id: Long, + public val extraArgs: TypeSafeMap = TypeSafeMap.EMPTY +) { + public companion object { + public val KEY_COMMAND_STR: TypeKey = TypeKey("KEY_COMMAND_STR") + public val KEY_BOT_PROTOCOL: TypeKey = TypeKey("BOT_PROTOCOL") + } +} + +/** + * @since 2.15.0 + */ +public interface EncryptService : BaseService { + /** + * Returns `null` if not supported. + */ + public fun encryptTlv( + context: EncryptServiceContext, + tlvType: Int, + payload: ByteArray, // Do not write to payload + ): ByteArray? + + public companion object { + private val loader = SpiServiceLoader(EncryptService::class) + + internal val instance: EncryptService? get() = loader.service + } +}