Commit 7189e620 authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

parents 91e9a5b0 c434b59f
...@@ -162,6 +162,11 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -162,6 +162,11 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
StatSvc.Register(bot.client).sendAndExpect<StatSvc.Register.Response>() StatSvc.Register(bot.client).sendAndExpect<StatSvc.Register.Response>()
} }
// caches
private val _pendingEnabled = atomic(true)
internal val pendingEnabled get() = _pendingEnabled.value
internal var pendingIncomingPackets: LockFreeLinkedList<KnownPacketFactories.IncomingPacket<*>>? = LockFreeLinkedList()
@UseExperimental(MiraiExperimentalAPI::class, ExperimentalTime::class) @UseExperimental(MiraiExperimentalAPI::class, ExperimentalTime::class)
override suspend fun init(): Unit = coroutineScope { override suspend fun init(): Unit = coroutineScope {
MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect() MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendWithoutExpect()
...@@ -265,6 +270,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -265,6 +270,15 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
} }
bot.firstLoginSucceed = true bot.firstLoginSucceed = true
_pendingEnabled.value = false
pendingIncomingPackets?.forEach {
@Suppress("UNCHECKED_CAST")
KnownPacketFactories.handleIncomingPacket(it as KnownPacketFactories.IncomingPacket<Packet>, bot, it.flag2, it.consumer)
}
pendingIncomingPackets = null // release
Unit
} }
suspend fun doHeartBeat(): Exception? { suspend fun doHeartBeat(): Exception? {
......
...@@ -211,34 +211,15 @@ internal object KnownPacketFactories { ...@@ -211,34 +211,15 @@ internal object KnownPacketFactories {
else -> error("unknown flag1: ${flag1.toByte().toUHexString()}") else -> error("unknown flag1: ${flag1.toByte().toUHexString()}")
} }
}?.let { }?.let {
if (it.packetFactory == null) { it as IncomingPacket<T>
bot.network.logger.debug("Received commandName: ${it.commandName}")
PacketLogger.warning { "找不到 PacketFactory" }
PacketLogger.verbose { "传递给 PacketFactory 的数据 = ${it.data.useBytes { data, length -> data.toUHexString(length = length) }}" }
return
}
it.data.withUse { if (it.packetFactory is IncomingPacketFactory<T> && bot.network.pendingEnabled) {
when (flag2) { bot.network.pendingIncomingPackets?.addLast(it.also {
0, 1 -> it.consumer = consumer
when (it.packetFactory) { it.flag2 = flag2
is OutgoingPacketFactory<*> -> consumer( }) ?: handleIncomingPacket(it, bot, flag2, consumer)
it.packetFactory as OutgoingPacketFactory<T>, } else {
it.packetFactory.run { decode(bot, it.data) }, handleIncomingPacket(it, bot, flag2, consumer)
it.packetFactory.commandName,
it.sequenceId
)
is IncomingPacketFactory<*> -> consumer(
it.packetFactory as IncomingPacketFactory<T>,
it.packetFactory.run { decode(bot, it.data, it.sequenceId) },
it.packetFactory.receivingCommandName,
it.sequenceId
)
}
2 -> it.data.parseOicqResponse(bot, it.packetFactory as OutgoingPacketFactory<T>, it.sequenceId, consumer)
else -> error("unknown flag2: $flag2. Body to be parsed for inner packet=${it.data.readBytes().toUHexString()}")
}
} }
} ?: inline { } ?: inline {
PacketLogger.error { "任何key都无法解密: ${data.take(size).toUHexString()}" } PacketLogger.error { "任何key都无法解密: ${data.take(size).toUHexString()}" }
...@@ -247,20 +228,56 @@ internal object KnownPacketFactories { ...@@ -247,20 +228,56 @@ internal object KnownPacketFactories {
} }
} }
@UseExperimental(MiraiInternalAPI::class)
internal suspend fun <T : Packet> handleIncomingPacket(it: IncomingPacket<T>, bot: QQAndroidBot, flag2: Int, consumer: PacketConsumer<T>) {
if (it.packetFactory == null) {
bot.network.logger.debug("Received commandName: ${it.commandName}")
PacketLogger.warning { "找不到 PacketFactory" }
PacketLogger.verbose { "传递给 PacketFactory 的数据 = ${it.data.useBytes { data, length -> data.toUHexString(length = length) }}" }
return
}
it.data.withUse {
when (flag2) {
0, 1 ->
when (it.packetFactory) {
is OutgoingPacketFactory<*> -> consumer(
it.packetFactory as OutgoingPacketFactory<T>,
it.packetFactory.run { decode(bot, it.data) },
it.packetFactory.commandName,
it.sequenceId
)
is IncomingPacketFactory<*> -> consumer(
it.packetFactory as IncomingPacketFactory<T>,
it.packetFactory.run { decode(bot, it.data, it.sequenceId) },
it.packetFactory.receivingCommandName,
it.sequenceId
)
}
2 -> it.data.parseOicqResponse(bot, it.packetFactory as OutgoingPacketFactory<T>, it.sequenceId, consumer)
else -> error("unknown flag2: $flag2. Body to be parsed for inner packet=${it.data.readBytes().toUHexString()}")
}
}
}
private inline fun <R> inline(block: () -> R): R = block() private inline fun <R> inline(block: () -> R): R = block()
class IncomingPacket( class IncomingPacket<T : Packet>(
val packetFactory: PacketFactory<*>?, val packetFactory: PacketFactory<T>?,
val sequenceId: Int, val sequenceId: Int,
val data: ByteReadPacket, val data: ByteReadPacket,
val commandName: String val commandName: String
) ) {
var flag2: Int = -1
lateinit var consumer: PacketConsumer<T>
}
/** /**
* 解析 SSO 层包装 * 解析 SSO 层包装
*/ */
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class) @UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
private fun parseSsoFrame(bot: QQAndroidBot, input: ByteReadPacket): IncomingPacket { private fun parseSsoFrame(bot: QQAndroidBot, input: ByteReadPacket): IncomingPacket<*> {
val commandName: String val commandName: String
val ssoSequenceId: Int val ssoSequenceId: Int
val dataCompressed: Int val dataCompressed: Int
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
package net.mamoe.mirai.event.internal package net.mamoe.mirai.event.internal
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.EventDisabled import net.mamoe.mirai.event.EventDisabled
...@@ -87,14 +88,22 @@ internal object EventListenerManager { ...@@ -87,14 +88,22 @@ internal object EventListenerManager {
private val registries = LockFreeLinkedList<Registry<*>>() private val registries = LockFreeLinkedList<Registry<*>>()
@Suppress("UNCHECKED_CAST") private val lock = atomic(false)
internal fun <E : Event> get(clazz: KClass<out E>): EventListeners<E> {
return registries.filteringGetOrAdd({ it.clazz == clazz }) { @Suppress("UNCHECKED_CAST", "BooleanLiteralArgument")
Registry( internal tailrec fun <E : Event> get(clazz: KClass<out E>): EventListeners<E> {
clazz, registries.forEach {
EventListeners() if (it.clazz == clazz) {
) return it.listeners as EventListeners<E>
}.listeners as EventListeners<E> }
}
if (lock.compareAndSet(false, true)) {
val registry = Registry(clazz, EventListeners())
registries.addLast(registry)
lock.value = false
return registry.listeners as EventListeners<E>
}
return get(clazz)
} }
} }
......
...@@ -216,21 +216,40 @@ object SilentLogger : PlatformLogger() { ...@@ -216,21 +216,40 @@ object SilentLogger : PlatformLogger() {
/** /**
* 简易日志记录, 所有类型日志都会被重定向 [logger] * 简易日志记录, 所有类型日志都会被重定向 [logger]
*/ */
class SimpleLogger(override val identity: String?, private val logger: (String?, Throwable?) -> Unit) : MiraiLoggerPlatformBase() { class SimpleLogger(
override val identity: String?,
private val logger: (priority: LogPriority, message: String?, e: Throwable?) -> Unit
) : MiraiLoggerPlatformBase() {
enum class LogPriority {
VERBOSE,
DEBUG,
INFO,
WARNING,
ERROR
}
companion object { companion object {
operator fun invoke(logger: (String?, Throwable?) -> Unit): SimpleLogger = SimpleLogger(null, logger) inline operator fun invoke(crossinline logger: (message: String?, e: Throwable?) -> Unit): SimpleLogger = SimpleLogger(null, logger)
inline operator fun invoke(identity: String?, crossinline logger: (message: String?, e: Throwable?) -> Unit): SimpleLogger =
SimpleLogger(identity) { _, message, e ->
logger(message, e)
}
operator fun invoke(logger: (priority: LogPriority, message: String?, e: Throwable?) -> Unit): SimpleLogger = SimpleLogger(null, logger)
} }
override fun verbose0(message: String?) = logger(message, null) override fun verbose0(message: String?) = logger(LogPriority.VERBOSE, message, null)
override fun verbose0(message: String?, e: Throwable?) = logger(message, e) override fun verbose0(message: String?, e: Throwable?) = logger(LogPriority.VERBOSE, message, e)
override fun debug0(message: String?) = logger(message, null) override fun debug0(message: String?) = logger(LogPriority.DEBUG, message, null)
override fun debug0(message: String?, e: Throwable?) = logger(message, e) override fun debug0(message: String?, e: Throwable?) = logger(LogPriority.DEBUG, message, e)
override fun info0(message: String?) = logger(message, null) override fun info0(message: String?) = logger(LogPriority.INFO, message, null)
override fun info0(message: String?, e: Throwable?) = logger(message, e) override fun info0(message: String?, e: Throwable?) = logger(LogPriority.INFO, message, e)
override fun warning0(message: String?) = logger(message, null) override fun warning0(message: String?) = logger(LogPriority.WARNING, message, null)
override fun warning0(message: String?, e: Throwable?) = logger(message, e) override fun warning0(message: String?, e: Throwable?) = logger(LogPriority.WARNING, message, e)
override fun error0(message: String?) = logger(message, null) override fun error0(message: String?) = logger(LogPriority.ERROR, message, null)
override fun error0(message: String?, e: Throwable?) = logger(message, e) override fun error0(message: String?, e: Throwable?) = logger(LogPriority.ERROR, message, e)
} }
/** /**
......
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