mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-08 17:20:11 +08:00
Fix retry when no Internet connection
This commit is contained in:
parent
ac6f411eb2
commit
fa211cab5c
@ -39,6 +39,7 @@ 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.io.readPacketExact
|
||||
import net.mamoe.mirai.qqandroid.utils.io.useBytes
|
||||
import net.mamoe.mirai.qqandroid.utils.retryCatching
|
||||
@ -127,9 +128,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
||||
|
||||
while (isActive) {
|
||||
try {
|
||||
channel.connect(host, port)
|
||||
channel.connect(coroutineContext + CoroutineName("Socket"), host, port)
|
||||
break
|
||||
} catch (e: NoRouteToHostException) {
|
||||
} catch (e: SocketException) {
|
||||
logger.warning { "No route to host (Mostly due to no Internet connection). Retrying in 3s..." }
|
||||
delay(3000)
|
||||
}
|
||||
|
@ -33,10 +33,12 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
|
||||
import net.mamoe.mirai.qqandroid.utils.ByteArrayPool
|
||||
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.io.serialization.readProtoBuf
|
||||
import net.mamoe.mirai.qqandroid.utils.io.withUse
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.copyAndClose
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
@OptIn(MiraiInternalAPI::class, InternalSerializationApi::class)
|
||||
@Suppress("SpellCheckingInspection")
|
||||
@ -117,9 +119,9 @@ internal object HighwayHelper {
|
||||
val socket = PlatformSocket()
|
||||
while (client.bot.network.isActive) {
|
||||
try {
|
||||
socket.connect(serverIp, serverPort)
|
||||
socket.connect(EmptyCoroutineContext, serverIp, serverPort)
|
||||
break
|
||||
} catch (e: NoRouteToHostException) {
|
||||
} catch (e: SocketException) {
|
||||
delay(3000)
|
||||
}
|
||||
}
|
||||
|
@ -13,13 +13,14 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.Closeable
|
||||
import kotlinx.io.errors.IOException
|
||||
import net.mamoe.mirai.utils.Throws
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* 多平台适配的 TCP Socket.
|
||||
*/
|
||||
internal expect class PlatformSocket() : Closeable {
|
||||
@Throws(NoRouteToHostException::class)
|
||||
suspend fun connect(serverHost: String, serverPort: Int)
|
||||
@Throws(SocketException::class)
|
||||
suspend fun connect(coroutineContext: CoroutineContext, serverHost: String, serverPort: Int)
|
||||
|
||||
/**
|
||||
* @throws SendPacketInternalException
|
||||
|
@ -27,7 +27,6 @@ import kotlin.jvm.JvmMultifileClass
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
@MiraiInternalAPI
|
||||
internal inline fun <R> ByteReadPacket.useBytes(
|
||||
n: Int = remaining.toInt(),//not that safe but adequate
|
||||
block: (data: ByteArray, length: Int) -> R
|
||||
@ -36,7 +35,6 @@ internal inline fun <R> ByteReadPacket.useBytes(
|
||||
block(it, n)
|
||||
}
|
||||
|
||||
@MiraiInternalAPI
|
||||
internal inline fun ByteReadPacket.readPacketExact(
|
||||
n: Int = remaining.toInt()//not that safe but adequate
|
||||
): ByteReadPacket = this.readBytes(n).toReadPacket()
|
||||
|
@ -21,6 +21,7 @@ import java.io.BufferedInputStream
|
||||
import java.io.BufferedOutputStream
|
||||
import java.net.Socket
|
||||
import java.net.SocketException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* 多平台适配的 TCP Socket.
|
||||
@ -81,7 +82,7 @@ internal actual class PlatformSocket : Closeable {
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalIoApi::class)
|
||||
actual suspend fun connect(serverHost: String, serverPort: Int) {
|
||||
actual suspend fun connect(coroutineContext: CoroutineContext, serverHost: String, serverPort: Int) {
|
||||
withContext(Dispatchers.IO) {
|
||||
socket = Socket(serverHost, serverPort)
|
||||
readChannel = socket.getInputStream().buffered()
|
||||
@ -92,4 +93,113 @@ internal actual class PlatformSocket : Closeable {
|
||||
|
||||
actual typealias NoRouteToHostException = java.net.NoRouteToHostException
|
||||
|
||||
actual typealias SocketException = SocketException
|
||||
actual typealias SocketException = SocketException
|
||||
|
||||
// ktor aSocket
|
||||
|
||||
/*
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.qqandroid.utils
|
||||
|
||||
import io.ktor.network.selector.ActorSelectorManager
|
||||
import io.ktor.network.sockets.*
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import io.ktor.utils.io.ByteReadChannel
|
||||
import io.ktor.utils.io.ByteWriteChannel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.Closeable
|
||||
import kotlinx.io.core.ExperimentalIoApi
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.errors.IOException
|
||||
import net.mamoe.mirai.qqandroid.utils.io.useBytes
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.SocketException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* 多平台适配的 TCP Socket.
|
||||
*/
|
||||
internal actual class PlatformSocket : Closeable {
|
||||
private lateinit var socket: io.ktor.network.sockets.Socket
|
||||
|
||||
actual val isOpen: Boolean
|
||||
get() =
|
||||
if (::socket.isInitialized)
|
||||
!socket.isClosed
|
||||
else false
|
||||
|
||||
actual override fun close() {
|
||||
if (::socket.isInitialized) {
|
||||
socket.close()
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal lateinit var writeChannel: ByteWriteChannel
|
||||
|
||||
@PublishedApi
|
||||
internal lateinit var readChannel: ByteReadChannel
|
||||
|
||||
actual suspend fun send(packet: ByteArray, offset: Int, length: Int) {
|
||||
withContext(Dispatchers.IO) {
|
||||
writeChannel.writeFully(packet, offset, length)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SendPacketInternalException
|
||||
*/
|
||||
actual suspend fun send(packet: ByteReadPacket) {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
packet.useBytes { data: ByteArray, length: Int ->
|
||||
writeChannel.writeFully(data, offset = 0, length = length)
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw SendPacketInternalException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ReadPacketInternalException
|
||||
*/
|
||||
actual suspend fun read(): ByteReadPacket {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
buildPacket {
|
||||
readChannel.read {
|
||||
writeFully(it)
|
||||
}
|
||||
}
|
||||
} catch (e: IOException) {
|
||||
throw ReadPacketInternalException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalIoApi::class, KtorExperimentalAPI::class)
|
||||
actual suspend fun connect(coroutineContext: CoroutineContext, serverHost: String, serverPort: Int) {
|
||||
withContext(Dispatchers.IO) {
|
||||
socket = aSocket(ActorSelectorManager(coroutineContext)).tcp().tcpNoDelay()
|
||||
.connect(InetSocketAddress(serverHost, serverPort))
|
||||
readChannel = socket.openReadChannel()
|
||||
writeChannel = socket.openWriteChannel(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual typealias NoRouteToHostException = java.net.NoRouteToHostException
|
||||
|
||||
actual typealias SocketException = SocketException
|
||||
*/
|
Loading…
Reference in New Issue
Block a user