Commit 2a379040 authored by Him188's avatar Him188

Fix the problem that login() function never returns

parent 62969444
...@@ -17,6 +17,7 @@ import net.mamoe.mirai.utils.BotConfiguration ...@@ -17,6 +17,7 @@ import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.DefaultLogger import net.mamoe.mirai.utils.DefaultLogger
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
import net.mamoe.mirai.utils.io.logStacktrace
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmOverloads
...@@ -75,7 +76,8 @@ suspend inline fun Bot(qq: Long, password: String): Bot = Bot(qq.toUInt(), passw ...@@ -75,7 +76,8 @@ suspend inline fun Bot(qq: Long, password: String): Bot = Bot(qq.toUInt(), passw
*/ */
class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineContext) : CoroutineScope { class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineContext) : CoroutineScope {
private val supervisorJob = SupervisorJob(context[Job]) private val supervisorJob = SupervisorJob(context[Job])
override val coroutineContext: CoroutineContext = context + supervisorJob override val coroutineContext: CoroutineContext =
context + supervisorJob + CoroutineExceptionHandler { _, e -> e.logStacktrace("An exception was thrown under a coroutine of Bot") }
constructor(qq: UInt, password: String, context: CoroutineContext) : this(BotAccount(qq, password), context) constructor(qq: UInt, password: String, context: CoroutineContext) : this(BotAccount(qq, password), context)
constructor(account: BotAccount, context: CoroutineContext) : this(account, DefaultLogger("Bot(" + account.id + ")"), context) constructor(account: BotAccount, context: CoroutineContext) : this(account, DefaultLogger("Bot(" + account.id + ")"), context)
...@@ -116,10 +118,10 @@ class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineCo ...@@ -116,10 +118,10 @@ class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineCo
* 然后重新启动并尝试登录 * 然后重新启动并尝试登录
*/ */
@JvmOverloads // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close @JvmOverloads // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close
fun reinitializeNetworkHandlerAsync( suspend fun reinitializeNetworkHandler(
configuration: BotConfiguration, configuration: BotConfiguration,
cause: Throwable? = null cause: Throwable? = null
): Deferred<LoginResult> = async { ): LoginResult {
logger.info("Initializing BotNetworkHandler") logger.info("Initializing BotNetworkHandler")
try { try {
if (::network.isInitialized) { if (::network.isInitialized) {
...@@ -129,9 +131,20 @@ class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineCo ...@@ -129,9 +131,20 @@ class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineCo
logger.error("Cannot close network handler", e) logger.error("Cannot close network handler", e)
} }
network = TIMBotNetworkHandler(coroutineContext + configuration, this@Bot) network = TIMBotNetworkHandler(coroutineContext + configuration, this@Bot)
network.login()
return network.login()
} }
/**
* [关闭][BotNetworkHandler.close]网络处理器, 取消所有运行在 [BotNetworkHandler] 下的协程.
* 然后重新启动并尝试登录
*/
@JvmOverloads // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close
fun reinitializeNetworkHandlerAsync(
configuration: BotConfiguration,
cause: Throwable? = null
): Deferred<LoginResult> = async { reinitializeNetworkHandler(configuration, cause) }
/** /**
* Bot 联系人管理. * Bot 联系人管理.
* *
......
...@@ -70,13 +70,13 @@ suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit ...@@ -70,13 +70,13 @@ suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit
contract { contract {
callsInPlace(configuration, InvocationKind.EXACTLY_ONCE) callsInPlace(configuration, InvocationKind.EXACTLY_ONCE)
} }
return this.reinitializeNetworkHandlerAsync(BotConfiguration().apply(configuration)).await() return this.reinitializeNetworkHandler(BotConfiguration().apply(configuration))
} }
/** /**
* 使用默认的配置 ([BotConfiguration.Default]) 登录, 返回登录结果 * 使用默认的配置 ([BotConfiguration.Default]) 登录, 返回登录结果
*/ */
suspend inline fun Bot.login(): LoginResult = this.reinitializeNetworkHandlerAsync(BotConfiguration.Default).await() suspend inline fun Bot.login(): LoginResult = this.reinitializeNetworkHandler(BotConfiguration.Default)
/** /**
* 使用默认的配置 ([BotConfiguration.Default]) 登录, 返回 [this] * 使用默认的配置 ([BotConfiguration.Default]) 登录, 返回 [this]
...@@ -91,7 +91,7 @@ suspend inline fun Bot.alsoLogin(noinline configuration: BotConfiguration.() -> ...@@ -91,7 +91,7 @@ suspend inline fun Bot.alsoLogin(noinline configuration: BotConfiguration.() ->
contract { contract {
callsInPlace(configuration, InvocationKind.EXACTLY_ONCE) callsInPlace(configuration, InvocationKind.EXACTLY_ONCE)
} }
this.reinitializeNetworkHandlerAsync(BotConfiguration().apply(configuration)).await().requireSuccess() this.reinitializeNetworkHandler(BotConfiguration().apply(configuration)).requireSuccess()
return this return this
} }
......
...@@ -58,8 +58,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -58,8 +58,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
private var heartbeatJob: Job? = null private var heartbeatJob: Job? = null
private lateinit var userContext: CoroutineContext
override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*, *>) { override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*, *>) {
handlersLock.withLock { handlersLock.withLock {
temporaryPacketHandlers.add(temporaryPacketHandler) temporaryPacketHandlers.add(temporaryPacketHandler)
...@@ -68,7 +66,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -68,7 +66,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
} }
override suspend fun login(): LoginResult { override suspend fun login(): LoginResult {
userContext = coroutineContext
return withContext(this.coroutineContext) { return withContext(this.coroutineContext) {
TIMProtocol.SERVER_IP.sortedBy { Random.nextInt() }.forEach { ip -> TIMProtocol.SERVER_IP.sortedBy { Random.nextInt() }.forEach { ip ->
bot.logger.info("Connecting server $ip") bot.logger.info("Connecting server $ip")
...@@ -97,10 +94,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -97,10 +94,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
override lateinit var session: BotSession override lateinit var session: BotSession
//private | internal //private | internal
private fun onLoggedIn() {
session = BotSession(sessionKey, socket)
bot.logger.info("Successfully logged in")
}
private var sessionKey: SessionKey by Delegates.notNull() private var sessionKey: SessionKey by Delegates.notNull()
...@@ -379,12 +372,10 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -379,12 +372,10 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
} }
is TouchPacket.TouchResponse.Redirection -> { is TouchPacket.TouchResponse.Redirection -> {
withContext(userContext) { socket.close()
socket.close() bot.logger.info("Redirecting to ${packet.serverIP}")
bot.logger.info("Redirecting to ${packet.serverIP}") socket = BotSocketAdapter(packet.serverIP!!)
socket = BotSocketAdapter(packet.serverIP!!) loginResult.complete(socket.resendTouch())
loginResult.complete(socket.resendTouch())
}
} }
is SubmitPasswordPacket.LoginResponse.Failed -> { is SubmitPasswordPacket.LoginResponse.Failed -> {
...@@ -417,14 +408,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -417,14 +408,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
if (packet.unknownBoolean) { if (packet.unknownBoolean) {
this.captchaSectionId = 1 this.captchaSectionId = 1
socket.sendPacket( socket.sendPacket(CaptchaPacket.RequestTransmission(bot.qqAccount, this.token0825, this.captchaSectionId++, packet.token00BA))
CaptchaPacket.RequestTransmission(
bot.qqAccount,
this.token0825,
this.captchaSectionId++,
packet.token00BA
)
)
} }
} }
...@@ -457,17 +441,13 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -457,17 +441,13 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
socket.sendPacket(CaptchaPacket.Submit(bot.qqAccount, token0825, code, packet.captchaToken)) socket.sendPacket(CaptchaPacket.Submit(bot.qqAccount, token0825, code, packet.captchaToken))
} }
} else { } else {
socket.sendPacket( socket.sendPacket(CaptchaPacket.RequestTransmission(bot.qqAccount, token0825, captchaSectionId++, packet.token00BA))
CaptchaPacket.RequestTransmission(bot.qqAccount, token0825, captchaSectionId++, packet.token00BA)
)
} }
} }
is SubmitPasswordPacket.LoginResponse.Success -> { is SubmitPasswordPacket.LoginResponse.Success -> {
this.sessionResponseDecryptionKey = packet.sessionResponseDecryptionKey this.sessionResponseDecryptionKey = packet.sessionResponseDecryptionKey
socket.sendPacket( socket.sendPacket(RequestSessionPacket(bot.qqAccount, socket.serverIp, packet.token38, packet.token88, packet.encryptionKey))
RequestSessionPacket(bot.qqAccount, socket.serverIp, packet.token38, packet.token88, packet.encryptionKey)
)
} }
//是ClientPasswordSubmissionPacket之后服务器回复的可能之一 //是ClientPasswordSubmissionPacket之后服务器回复的可能之一
...@@ -493,6 +473,15 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -493,6 +473,15 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
sessionKey = packet.sessionKey sessionKey = packet.sessionKey
bot.logger.info("sessionKey = ${sessionKey.value.toUHexString()}") bot.logger.info("sessionKey = ${sessionKey.value.toUHexString()}")
setOnlineStatus(OnlineStatus.ONLINE)//required
}
is ChangeOnlineStatusPacket.ChangeOnlineStatusResponse -> {
BotLoginSucceedEvent(bot).broadcast()
session = BotSession(sessionKey, socket)
val configuration = currentBotConfiguration() val configuration = currentBotConfiguration()
heartbeatJob = this@TIMBotNetworkHandler.launch { heartbeatJob = this@TIMBotNetworkHandler.launch {
while (socket.isOpen) { while (socket.isOpen) {
...@@ -514,15 +503,8 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -514,15 +503,8 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
} }
} }
bot.logger.info("Successfully logged in")
loginResult.complete(LoginResult.SUCCESS) loginResult.complete(LoginResult.SUCCESS)
setOnlineStatus(OnlineStatus.ONLINE)//required
}
is ChangeOnlineStatusPacket.ChangeOnlineStatusResponse -> {
BotLoginSucceedEvent(bot).broadcast()
onLoggedIn()
this.close()//The LoginHandler is useless since then this.close()//The LoginHandler is useless since then
} }
} }
......
...@@ -113,7 +113,8 @@ inline fun LoginResult.requireSuccess(lazyMessage: (LoginResult) -> String) { ...@@ -113,7 +113,8 @@ inline fun LoginResult.requireSuccess(lazyMessage: (LoginResult) -> String) {
* 检查 [this] 为 [LoginResult.SUCCESS]. * 检查 [this] 为 [LoginResult.SUCCESS].
* 失败则 [error] * 失败则 [error]
*/ */
fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" } @Suppress("NOTHING_TO_INLINE")
inline fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" }
/** /**
* 检查 [this] 为 [LoginResult.SUCCESS]. * 检查 [this] 为 [LoginResult.SUCCESS].
...@@ -121,7 +122,8 @@ fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" } ...@@ -121,7 +122,8 @@ fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" }
* *
* @return 成功时 [Unit], 失败时 `null` * @return 成功时 [Unit], 失败时 `null`
*/ */
fun LoginResult.requireSuccessOrNull(): Unit? = if (this == SUCCESS) Unit else null @Suppress("NOTHING_TO_INLINE")
inline fun LoginResult.requireSuccessOrNull(): Unit? = if (this == SUCCESS) Unit else null
/** /**
* 返回 [this] 是否为 [LoginResult.SUCCESS]. * 返回 [this] 是否为 [LoginResult.SUCCESS].
......
...@@ -12,6 +12,7 @@ internal object DebugLogger : MiraiLogger by DefaultLogger("Packet Debug") ...@@ -12,6 +12,7 @@ internal object DebugLogger : MiraiLogger by DefaultLogger("Packet Debug")
internal fun Throwable.logStacktrace(message: String? = null) = DebugLogger.error(message, this) internal fun Throwable.logStacktrace(message: String? = null) = DebugLogger.error(message, this)
@PublishedApi
internal fun debugPrintln(any: Any?) = DebugLogger.debug(any) internal fun debugPrintln(any: Any?) = DebugLogger.debug(any)
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith("this")) @Deprecated("Low efficiency, only for debug purpose", ReplaceWith("this"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment