From 2a641415a70db24d74beb6d2159e27126bd5f149 Mon Sep 17 00:00:00 2001 From: Karlatemp Date: Sun, 18 Jul 2021 23:13:47 +0800 Subject: [PATCH] Fix network not reconnect when received `ReqMSFOffline` --- .../src/commonMain/kotlin/QQAndroidBot.kt | 4 +++ .../network/protocol/packet/login/StatSvc.kt | 28 +++++++++++++------ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt b/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt index 5db01fea0..4bbc551cb 100644 --- a/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt +++ b/mirai-core/src/commonMain/kotlin/QQAndroidBot.kt @@ -42,6 +42,7 @@ import net.mamoe.mirai.internal.network.handler.state.StateObserver import net.mamoe.mirai.internal.network.handler.state.safe import net.mamoe.mirai.internal.network.impl.netty.ForceOfflineException import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandlerFactory +import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc import net.mamoe.mirai.internal.utils.subLogger import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.MiraiLogger @@ -119,6 +120,9 @@ internal open class QQAndroidBot constructor( cause is ForceOfflineException -> { eventDispatcher.broadcastAsync(BotOfflineEvent.Force(bot, cause.title, cause.message)) } + cause is StatSvc.ReqMSFOffline.MsfOfflineToken -> { + eventDispatcher.broadcastAsync(BotOfflineEvent.MsfOffline(bot, cause)) + } cause is NetworkException && cause.recoverable -> { eventDispatcher.broadcastAsync(BotOfflineEvent.Dropped(bot, cause)) } diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/StatSvc.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/StatSvc.kt index 585b3dd59..55a5fdf94 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/StatSvc.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/StatSvc.kt @@ -20,7 +20,6 @@ import net.mamoe.mirai.contact.ClientKind import net.mamoe.mirai.contact.OtherClientInfo import net.mamoe.mirai.contact.Platform import net.mamoe.mirai.data.OnlineStatus -import net.mamoe.mirai.event.events.BotOfflineEvent import net.mamoe.mirai.event.events.OtherClientOfflineEvent import net.mamoe.mirai.event.events.OtherClientOnlineEvent import net.mamoe.mirai.internal.QQAndroidBot @@ -31,6 +30,7 @@ import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.components.ContactCacheService import net.mamoe.mirai.internal.network.components.ContactUpdater import net.mamoe.mirai.internal.network.components.ServerList +import net.mamoe.mirai.internal.network.handler.selector.NetworkException import net.mamoe.mirai.internal.network.impl.netty.HeartbeatFailedException import net.mamoe.mirai.internal.network.protocol.data.jce.* import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x769 @@ -268,24 +268,29 @@ internal class StatSvc { } internal object ReqMSFOffline : - IncomingPacketFactory("StatSvc.ReqMSFOffline", "StatSvc.RspMSFForceOffline") { + IncomingPacketFactory("StatSvc.ReqMSFOffline", "StatSvc.RspMSFForceOffline") { + + internal class MsfOfflinePacket( + val token: MsfOfflineToken, + ) : Packet { + override fun toString(): String = "StatSvc.ReqMSFOffline" + } internal data class MsfOfflineToken( val uin: Long, val seq: Long, val const: Byte - ) : Packet, RuntimeException("dropped by StatSvc.ReqMSFOffline") + ) : Packet, NetworkException("dropped by StatSvc.ReqMSFOffline", true) - override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): BotOfflineEvent.MsfOffline { + override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): MsfOfflinePacket { val decodeUniPacket = readUniPacket(RequestMSFForceOffline.serializer()) @Suppress("INVISIBLE_MEMBER") - return BotOfflineEvent.MsfOffline(bot, MsfOfflineToken(decodeUniPacket.uin, decodeUniPacket.iSeqno, 0)) + return MsfOfflinePacket(MsfOfflineToken(decodeUniPacket.uin, decodeUniPacket.iSeqno, 0)) } - override suspend fun QQAndroidBot.handle(packet: BotOfflineEvent.MsfOffline, sequenceId: Int): OutgoingPacket { - val cause = packet.cause - check(cause is MsfOfflineToken) { "internal error: handling $packet in StatSvc.ReqMSFOffline" } - return buildResponseUniPacket(client) { + override suspend fun QQAndroidBot.handle(packet: MsfOfflinePacket, sequenceId: Int): OutgoingPacket? { + val cause = packet.token + val resp = buildResponseUniPacket(client) { writeJceStruct( RequestPacket.serializer(), RequestPacket( @@ -304,6 +309,11 @@ internal class StatSvc { ) ) } + kotlin.runCatching { + bot.network.sendWithoutExpect(resp) + } + bot.network.close(cause) + return null } }