Break network when received LoginFailedException; fix #1352

This commit is contained in:
Karlatemp
2021-06-22 13:35:43 +08:00
parent 7b0552558b
commit d1fdddf9e6
7 changed files with 47 additions and 13 deletions

View File

@@ -25,6 +25,7 @@ import net.mamoe.mirai.internal.network.components.SsoProcessor
import net.mamoe.mirai.internal.network.handler.NetworkHandler
import net.mamoe.mirai.internal.network.handler.selector.NetworkException
import net.mamoe.mirai.internal.network.impl.netty.asCoroutineExceptionHandler
import net.mamoe.mirai.network.LoginFailedException
import net.mamoe.mirai.supervisorJob
import net.mamoe.mirai.utils.*
import kotlin.collections.set
@@ -123,6 +124,9 @@ internal abstract class AbstractBot constructor(
if (!components[SsoProcessor].firstLoginSucceed) {
this.close(cause) // failed to do first login.
}
if (cause is LoginFailedException && cause.killBot) {
close(cause)
}
throw cause
}
logger.info { "Bot login successful." }

View File

@@ -15,6 +15,8 @@ import kotlinx.coroutines.yield
import net.mamoe.mirai.internal.network.handler.NetworkHandler
import net.mamoe.mirai.internal.network.handler.NetworkHandlerFactory
import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.network.LoginFailedException
import net.mamoe.mirai.network.RetryLaterException
import net.mamoe.mirai.utils.ExceptionCollector
import net.mamoe.mirai.utils.systemProp
import net.mamoe.mirai.utils.toLongUnsigned
@@ -85,6 +87,13 @@ internal abstract class AbstractKeepAliveNetworkHandlerSelector<H : NetworkHandl
suspend fun H.resumeInstanceCatchingException() {
try {
resumeConnection() // once finished, it should has been LOADING or OK
} catch (e: LoginFailedException) {
if (e is RetryLaterException) {
close(e)
return
}
// LoginFailedException is not resumable
exceptionCollector.collectThrow(e)
} catch (e: Exception) {
close(e)
// exception will be collected by `exceptionCollector.collectException(current.getLastFailure())`

View File

@@ -129,9 +129,10 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
// set(StateObserver, bot.run { stateObserverChain() })
}
open fun createHandler(): H = factory.create(createContext(), address)
open fun createHandler(): NetworkHandler = factory.create(createContext(), address)
open fun createContext(): NetworkHandlerContextImpl =
NetworkHandlerContextImpl(bot, networkLogger, bot.createNetworkLevelComponents())
val address: InetSocketAddress = InetSocketAddress.createUnresolved("localhost", 123)
///////////////////////////////////////////////////////////////////////////
@@ -147,4 +148,10 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
}
val eventDispatcher get() = bot.components[EventDispatcher]
}
}
internal fun AbstractRealNetworkHandlerTest<*>.setSsoProcessor(action: suspend SsoProcessor.(handler: NetworkHandler) -> Unit) {
overrideComponents[SsoProcessor] = object : SsoProcessor by overrideComponents[SsoProcessor] {
override suspend fun login(handler: NetworkHandler) = action(handler)
}
}

View File

@@ -93,9 +93,3 @@ internal abstract class AbstractNettyNHTest : AbstractRealNetworkHandlerTest<Tes
}
}
}
internal fun AbstractNettyNHTest.setSsoProcessor(action: suspend SsoProcessor.(handler: NetworkHandler) -> Unit) {
overrideComponents[SsoProcessor] = object : SsoProcessor by overrideComponents[SsoProcessor] {
override suspend fun login(handler: NetworkHandler) = action(handler)
}
}

View File

@@ -10,29 +10,47 @@
package net.mamoe.mirai.internal.network.impl.netty
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.isActive
import net.mamoe.mirai.internal.network.framework.setSsoProcessor
import net.mamoe.mirai.internal.network.handler.NetworkHandler
import net.mamoe.mirai.internal.network.handler.selector.KeepAliveNetworkHandlerSelector
import net.mamoe.mirai.internal.network.handler.selector.SelectorNetworkHandler
import net.mamoe.mirai.internal.test.runBlockingUnit
import net.mamoe.mirai.network.CustomLoginFailedException
import org.junit.jupiter.api.Test
import java.io.IOException
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
internal class NettyBotNormalLoginTest : AbstractNettyNHTest() {
class CusLoginException(message: String?) : RuntimeException(message)
val selector = KeepAliveNetworkHandlerSelector {
super.factory.create(createContext(), address)
}
override fun createHandler(): NetworkHandler {
return SelectorNetworkHandler(selector)
}
class CusLoginException(message: String?) : CustomLoginFailedException(true, message)
@Test
fun `test login fail`() = runBlockingUnit {
setSsoProcessor { throw CusLoginException("A") }
assertFailsWith<CusLoginException>("A") { bot.login() }
assertFalse(bot.isActive)
}
@Test
fun `test network broken`() = runBlockingUnit {
var retryCounter = 0
setSsoProcessor {
eventDispatcher.joinBroadcast()
if (retryCounter++ >= 15) {
return@setSsoProcessor
}
channel.pipeline().fireExceptionCaught(IOException("TestNetworkBroken"))
awaitCancellation() // receive exception from "network"
}
assertFailsWith<IOException>("TestNetworkBroken") {
bot.login()
}
bot.login()
}
}

View File

@@ -17,6 +17,7 @@ import net.mamoe.mirai.event.events.BotOnlineEvent
import net.mamoe.mirai.event.events.BotReloginEvent
import net.mamoe.mirai.internal.network.components.SsoProcessor
import net.mamoe.mirai.internal.network.framework.eventDispatcher
import net.mamoe.mirai.internal.network.framework.setSsoProcessor
import net.mamoe.mirai.internal.network.framework.ssoProcessor
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State.*
import net.mamoe.mirai.internal.test.assertEventBroadcasts

View File

@@ -24,7 +24,8 @@ abstract class AbstractTest {
init {
initPlatform()
System.setProperty("mirai.debug.network.state.observer.logging", "false")
System.setProperty("mirai.debug.network.packet.logger", "true")
System.setProperty("mirai.debug.network.state.observer.logging", "true")
System.setProperty("mirai.debug.network.show.all.components", "true")
System.setProperty("mirai.debug.network.show.components.creation.stacktrace", "true")