Add PacketInterceptor

This commit is contained in:
Karlatemp 2021-06-19 02:27:33 +08:00
parent e816755414
commit 04656d7a03
No known key found for this signature in database
GPG Key ID: 21FBDDF664FF06F8
2 changed files with 89 additions and 4 deletions

View File

@ -160,8 +160,10 @@ internal open class QQAndroidBot constructor(
)
set(ServerList, ServerListImpl(networkLogger.subLogger("ServerList")))
set(PacketLoggingStrategy, PacketLoggingStrategyImpl(bot))
set(PacketInterceptor, PacketInterceptorImpl())
set(
PacketHandler, PacketHandlerChain(
components,
LoggingPacketHandlerAdapter(get(PacketLoggingStrategy), networkLogger),
EventBroadcasterPacketHandler(components),
CallPacketFactoryPacketHandler(bot)

View File

@ -20,6 +20,7 @@ import net.mamoe.mirai.internal.network.component.ComponentStorage
import net.mamoe.mirai.internal.network.protocol.packet.*
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.cast
import java.util.concurrent.ConcurrentLinkedDeque
import kotlin.coroutines.cancellation.CancellationException
internal interface PacketHandler {
@ -29,15 +30,29 @@ internal interface PacketHandler {
}
internal class PacketHandlerChain(
private val components: ComponentStorage = ComponentStorage.EMPTY,
private val instances: Collection<PacketHandler>
) : PacketHandler {
constructor(vararg instances: PacketHandler?) : this(instances.filterNotNull())
constructor(instances: Iterable<PacketHandler?>) : this(instances.filterNotNull())
constructor(
components: ComponentStorage = ComponentStorage.EMPTY,
vararg instances: PacketHandler?,
) : this(components, instances.filterNotNull())
constructor(
components: ComponentStorage = ComponentStorage.EMPTY,
instances: Iterable<PacketHandler?>,
) : this(components, instances.filterNotNull())
private val interceptor: PacketInterceptor by lazy {
components.getOrNull(PacketInterceptor) ?: PacketInterceptor.NO
}
override suspend fun handlePacket(incomingPacket: IncomingPacket) {
val p = interceptor.interceptor(incomingPacket) ?: return
for (instance in instances) {
try {
instance.handlePacket(incomingPacket)
instance.handlePacket(p)
} catch (e: Throwable) {
if (e is CancellationException) return
throw ExceptionInPacketHandlerException(instance, incomingPacket, e)
@ -111,4 +126,72 @@ internal class CallPacketFactoryPacketHandler(
}
override fun toString(): String = "CallPacketFactoryPacketHandler"
}
}
internal interface PacketInterceptor {
/**
* Break packet handling chain if return `null`
*/
suspend fun interceptor(incomingPacket: IncomingPacket): IncomingPacket?
fun registerTemporaryInterceptor(
block: suspend PacketTemporaryInterceptor.(
PacketTemporaryInterceptor.Context,
IncomingPacket,
) -> Unit
): PacketTemporaryInterceptor
companion object : ComponentKey<PacketInterceptor> {
val NO: PacketInterceptor = object : PacketInterceptor {
override suspend fun interceptor(incomingPacket: IncomingPacket): IncomingPacket? {
return incomingPacket
}
override fun registerTemporaryInterceptor(block: suspend PacketTemporaryInterceptor.(PacketTemporaryInterceptor.Context, IncomingPacket) -> Unit): PacketTemporaryInterceptor {
throw UnsupportedOperationException()
}
}
}
}
internal interface PacketTemporaryInterceptor {
interface Context {
suspend fun finished()
}
fun unregister()
}
internal class PacketInterceptorImpl : PacketInterceptor {
private val interceptors = ConcurrentLinkedDeque<PacketTemporaryInterceptorImpl>()
private inner class PacketTemporaryInterceptorImpl(
@JvmField val func: suspend PacketTemporaryInterceptor.(PacketTemporaryInterceptor.Context, IncomingPacket) -> Unit,
) : PacketTemporaryInterceptor {
override fun unregister() {
interceptors.remove(this)
}
}
override suspend fun interceptor(incomingPacket: IncomingPacket): IncomingPacket? {
val context = object : PacketTemporaryInterceptor.Context {
var f = false
override suspend fun finished() {
f = true
}
}
interceptors.forEach { interceptor ->
if (context.f) return null
interceptor.func.invoke(interceptor, context, incomingPacket)
}
if (context.f) return null
return incomingPacket
}
override fun registerTemporaryInterceptor(block: suspend PacketTemporaryInterceptor.(PacketTemporaryInterceptor.Context, IncomingPacket) -> Unit): PacketTemporaryInterceptor {
val i = PacketTemporaryInterceptorImpl(block)
this.interceptors.add(i)
return i
}
}