Parcourir la source

Fix network UnknownHostException handling

Him188 il y a 5 ans
Parent
commit
2bfffa7b29

+ 3 - 1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt

@@ -215,7 +215,9 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
 
     init {
         coroutineContext[Job]!!.invokeOnCompletion { throwable ->
-            network.close(throwable)
+            kotlin.runCatching {
+                network.close(throwable)
+            }
             offlineListener.cancel(CancellationException("Bot cancelled", throwable))
 
             // help GC release instances

+ 11 - 7
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt

@@ -38,12 +38,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.ConfigPushSvc
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.Heartbeat
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.WtLogin
-import net.mamoe.mirai.qqandroid.utils.NoRouteToHostException
-import net.mamoe.mirai.qqandroid.utils.PlatformSocket
-import net.mamoe.mirai.qqandroid.utils.SocketException
+import net.mamoe.mirai.qqandroid.utils.*
 import net.mamoe.mirai.qqandroid.utils.io.readPacketExact
 import net.mamoe.mirai.qqandroid.utils.io.useBytes
-import net.mamoe.mirai.qqandroid.utils.retryCatching
 import net.mamoe.mirai.utils.*
 import kotlin.coroutines.CoroutineContext
 import kotlin.jvm.JvmField
@@ -137,6 +134,13 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
                 } else {
                     throw e
                 }
+            } catch (e: UnknownHostException) {
+                if (e is NoRouteToHostException || e.message?.contains("Network is unreachable") == true) {
+                    logger.warning { "No route to host (Mostly due to no Internet connection). Retrying in 3s..." }
+                    delay(3000)
+                } else {
+                    throw e
+                }
             }
         }
         logger.info { "Connected to server $host:$port" }
@@ -627,6 +631,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
 
         check(bot.isActive) { "bot is dead therefore can't send ${this.commandName}" }
         check([email protected]) { "network is dead therefore can't send any packet" }
+        check(channel.isOpen) { "network channel is closed" }
 
         suspend fun doSendAndReceive(handler: PacketListener, data: Any, length: Int): E {
             when (data) {
@@ -637,10 +642,9 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
             logger.verbose { "Send: $commandName" }
 
             @Suppress("UNCHECKED_CAST")
-            return withTimeoutOrNull(timeoutMillis) {
+            return withTimeout(timeoutMillis) {
                 handler.await()
-                // 不要 `withTimeout`. timeout 的报错会不正常.
-            } as E? ?: throw TimeoutException("timeout receiving response of $commandName")
+            } as E
         }
 
         if (retry == 0) {

+ 2 - 1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt

@@ -43,4 +43,5 @@ internal expect class PlatformSocket() : Closeable {
 }
 
 expect open class SocketException : IOException
-expect class NoRouteToHostException : SocketException
+expect class NoRouteToHostException : SocketException
+expect class UnknownHostException : IOException

+ 2 - 1
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/PlatformSocket.kt

@@ -201,4 +201,5 @@ internal actual class PlatformSocket : Closeable {
 actual typealias NoRouteToHostException = java.net.NoRouteToHostException
 
 actual typealias SocketException = SocketException
- */
+ */
+actual typealias UnknownHostException = java.net.UnknownHostException