diff --git a/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt b/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt index 488d21119..d23188e90 100644 --- a/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt +++ b/mirai-core/src/commonMain/kotlin/network/handler/NetworkHandlerSupport.kt @@ -183,7 +183,7 @@ internal abstract class NetworkHandlerSupport( * You may need to call [BaseStateImpl.resumeConnection] to activate the new state, as states are lazy. */ protected inline fun setState(crossinline new: () -> S): S = synchronized(this) { - // we can add hooks here for debug. + if (_state.correspondingState == NetworkHandler.State.CLOSED) error("Cannot change state while it has already been CLOSED.") val stateObserver = context.getOrNull(StateObserver) diff --git a/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt index d265634d2..bd1b7134f 100644 --- a/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/network/impl/netty/NettyNetworkHandler.kt @@ -118,7 +118,8 @@ internal class NettyNetworkHandler( } future.channel().closeFuture().addListener { - setState { StateConnectionLost(it.cause()) } + if (_state.correspondingState == State.CLOSED) return@addListener + setState { StateConnecting(ExceptionCollector(it.cause())) } } return contextResult.await() @@ -189,9 +190,15 @@ internal class NettyNetworkHandler( * * Dropped when state becomes [StateOK]. */ - private val collectiveExceptions: ExceptionCollector + private val collectiveExceptions: ExceptionCollector, + wait: Boolean = false ) : NettyState(State.CONNECTING) { - private val connection = async { createConnection(decodePipeline) } + private val connection = async { + if (wait) { + delay(5000) + } + createConnection(decodePipeline) + } private val connectResult = async { connection.join() @@ -199,8 +206,9 @@ internal class NettyNetworkHandler( }.apply { invokeOnCompletion { error -> if (error != null) setState { - StateClosed( - CancellationException("Connection failure.", collectiveExceptions.collectGet(error)) + StateConnecting( + collectiveExceptions.apply { collect(error) }, + wait = true ) } // logon failure closes the network handler. // and this error will also be thrown by `StateConnecting.resumeConnection`