Fix #470: Network Protocol: java.lang.IllegalStateException: returnCode = -10008

This commit is contained in:
Him188 2020-07-31 22:49:07 +08:00
parent 9a9ff4a58e
commit 43407aa427
5 changed files with 53 additions and 20 deletions

View File

@ -82,7 +82,8 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
when (event) {
is BotOfflineEvent.MsfOffline,
is BotOfflineEvent.Dropped,
is BotOfflineEvent.RequireReconnect
is BotOfflineEvent.RequireReconnect,
is BotOfflineEvent.PacketFactory10008
-> {
if (!_network.isActive) {
// normally closed

View File

@ -24,6 +24,7 @@ import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.events.BotOnlineEvent
import net.mamoe.mirai.event.events.BotReloginEvent
import net.mamoe.mirai.message.MessageEvent
import net.mamoe.mirai.network.ForceOfflineException
import net.mamoe.mirai.network.RetryLaterException
import net.mamoe.mirai.network.UnsupportedSMSLoginException
import net.mamoe.mirai.network.WrongPasswordException
@ -32,6 +33,7 @@ import net.mamoe.mirai.qqandroid.contact.*
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.StTroopNum
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories.PacketFactoryIllegalState10008Exception
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbGetMsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
@ -456,7 +458,14 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
return this.launch(
start = CoroutineStart.ATOMIC
) {
input.use { parsePacket(it) }
input.use {
try {
parsePacket(it)
} catch (e: PacketFactoryIllegalState10008Exception) {
logger.warning { "Network force offline: ${e.message}" }
bot.launch { BotOfflineEvent.PacketFactory10008(bot, e).broadcast() }
}
}
}
}
@ -466,6 +475,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
*
* @param input 一个完整的包的内容, 去掉开头的 int 包长度
*/
@Throws(ForceOfflineException::class)
suspend fun parsePacket(input: ByteReadPacket) {
generifiedParsePacket<Packet>(input)
}

View File

@ -37,6 +37,7 @@ import net.mamoe.mirai.qqandroid.utils.io.useBytes
import net.mamoe.mirai.qqandroid.utils.io.withUse
import net.mamoe.mirai.utils.*
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
internal sealed class PacketFactory<TPacket : Packet?> {
/**
@ -176,6 +177,11 @@ internal object KnownPacketFactories {
?: IncomingFactories.firstOrNull { it.receivingCommandName == commandName }
}
class PacketFactoryIllegalState10008Exception @JvmOverloads constructor(
override val message: String? = null,
override val cause: Throwable? = null
) : RuntimeException()
// do not inline. Exceptions thrown will not be reported correctly
@Suppress("UNCHECKED_CAST")
suspend fun <T : Packet?> parseIncomingPacket(
@ -247,11 +253,13 @@ internal object KnownPacketFactories {
bot.network.logger.debug { "Received unknown commandName: ${it.commandName}" }
PacketLogger.warning { "找不到 PacketFactory" }
PacketLogger.verbose {
"传递给 PacketFactory 的数据 = ${it.data.useBytes { data, length ->
"传递给 PacketFactory 的数据 = ${
it.data.useBytes { data, length ->
data.toUHexString(
length = length
)
}}"
}
}"
}
return
}
@ -304,8 +312,14 @@ internal object KnownPacketFactories {
input.readPacketExact(input.readInt() - 4).withUse {
ssoSequenceId = readInt()
PacketLogger.verbose { "sequenceId = $ssoSequenceId" }
val returnCode = readInt()
check(returnCode == 0) { "returnCode = $returnCode" }
check(returnCode == 0) {
if (returnCode == -10008) { // https://github.com/mamoe/mirai/issues/470
throw PacketFactoryIllegalState10008Exception("returnCode = $returnCode")
} else "returnCode = $returnCode"
}
if (PacketLogger.isEnabled) {
val extraData = readBytes(readInt() - 4)
PacketLogger.verbose { "(sso/inner)extraData = ${extraData.toUHexString()}" }

View File

@ -43,8 +43,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
public data class Active(
public override val bot: Bot,
public override val cause: Throwable?
) : BotOfflineEvent(), BotActiveEvent,
CauseAware
) : BotOfflineEvent(), BotActiveEvent, CauseAware
/**
* 被挤下线
@ -53,9 +52,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
public override val bot: Bot,
public val title: String,
public val message: String
) :
BotOfflineEvent(), Packet,
BotPassiveEvent
) : BotOfflineEvent(), Packet, BotPassiveEvent
/**
* 被服务器断开
@ -65,9 +62,7 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
public data class MsfOffline internal constructor(
public override val bot: Bot,
public override val cause: Throwable?
) :
BotOfflineEvent(), Packet,
BotPassiveEvent, CauseAware
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware
/**
* 因网络问题而掉线
@ -75,9 +70,17 @@ public sealed class BotOfflineEvent : BotEvent, AbstractEvent() {
public data class Dropped internal constructor(
public override val bot: Bot,
public override val cause: Throwable?
) : BotOfflineEvent(),
Packet,
BotPassiveEvent, CauseAware
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware
/**
* returnCode = -10008 等原因掉线
*/
@MiraiInternalAPI("This is very experimental and might be changed")
@SinceMirai("1.2.0")
public data class PacketFactory10008 internal constructor(
public override val bot: Bot,
public override val cause: Throwable
) : BotOfflineEvent(), Packet, BotPassiveEvent, CauseAware
/**
* 服务器主动要求更换另一个服务器

View File

@ -3,8 +3,13 @@ package net.mamoe.mirai.network
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Job
import net.mamoe.mirai.Bot
import kotlin.jvm.JvmOverloads
/**
* [Bot] 被迫下线时抛出, 作为 [Job.cancel] `cause`
*/
public class ForceOfflineException(public override val message: String?) : CancellationException(message)
public class ForceOfflineException
@JvmOverloads constructor(
public override val message: String? = null,
public override val cause: Throwable? = null
) : CancellationException(message)