Commit ad43a92b authored by Him188's avatar Him188

Use PacketHandler.Key

parent d89f8acc
...@@ -7,8 +7,10 @@ import net.mamoe.mirai.contact.Group ...@@ -7,8 +7,10 @@ import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler import net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
import net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import net.mamoe.mirai.utils.BotAccount import net.mamoe.mirai.utils.BotAccount
import net.mamoe.mirai.utils.ContactList import net.mamoe.mirai.utils.ContactList
import net.mamoe.mirai.utils.LoginConfiguration
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
/** /**
...@@ -44,7 +46,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) { ...@@ -44,7 +46,7 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
val contacts = ContactSystem() val contacts = ContactSystem()
val network: BotNetworkHandler<*> = TIMBotNetworkHandler(this) var network: BotNetworkHandler<*> = TIMBotNetworkHandler(this)
init { init {
instances.add(this) instances.add(this)
...@@ -54,6 +56,17 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) { ...@@ -54,6 +56,17 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
override fun toString(): String = "Bot{id=$id,qq=${account.qqNumber}}" override fun toString(): String = "Bot{id=$id,qq=${account.qqNumber}}"
/**
* [关闭][BotNetworkHandler.close]网络处理器, 取消所有运行在 [BotNetworkHandler.NetworkScope] 下的协程.
* 然后重新启动并尝试登录
*/
suspend fun reinitializeNetworkHandler(configuration: LoginConfiguration): LoginResult {
logger.logPurple("Reinitializing BotNetworkHandler")
network.close()
network = TIMBotNetworkHandler(this)
return network.login(configuration)
}
/** /**
* Bot 联系人管理. * Bot 联系人管理.
* *
......
...@@ -3,6 +3,7 @@ package net.mamoe.mirai.contact ...@@ -3,6 +3,7 @@ package net.mamoe.mirai.contact
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Group.Companion.groupNumberToId import net.mamoe.mirai.contact.Group.Companion.groupNumberToId
import net.mamoe.mirai.message.MessageChain import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler
import net.mamoe.mirai.utils.ContactList import net.mamoe.mirai.utils.ContactList
import kotlin.jvm.JvmStatic import kotlin.jvm.JvmStatic
...@@ -28,7 +29,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number) { ...@@ -28,7 +29,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number) {
get() = throw UnsupportedOperationException("Not yet supported") get() = throw UnsupportedOperationException("Not yet supported")
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
bot.network.event.sendGroupMessage(this, message) bot.network[EventPacketHandler].sendGroupMessage(this, message)
} }
override suspend fun sendXMLMessage(message: String) { override suspend fun sendXMLMessage(message: String) {
......
...@@ -4,6 +4,7 @@ import net.mamoe.mirai.Bot ...@@ -4,6 +4,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.message.At import net.mamoe.mirai.message.At
import net.mamoe.mirai.message.Message import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.MessageChain import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler
/** /**
* QQ 账号. * QQ 账号.
...@@ -19,7 +20,7 @@ import net.mamoe.mirai.message.MessageChain ...@@ -19,7 +20,7 @@ import net.mamoe.mirai.message.MessageChain
*/ */
class QQ(bot: Bot, number: Long) : Contact(bot, number) { class QQ(bot: Bot, number: Long) : Contact(bot, number) {
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
bot.network.event.sendFriendMessage(this, message) bot.network[EventPacketHandler].sendFriendMessage(this, message)
} }
override suspend fun sendXMLMessage(message: String) { override suspend fun sendXMLMessage(message: String) {
......
...@@ -6,7 +6,7 @@ import kotlinx.io.core.* ...@@ -6,7 +6,7 @@ import kotlinx.io.core.*
import net.mamoe.mirai.message.* import net.mamoe.mirai.message.*
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
internal fun ByteArray.parseMessageFace(): Face = read { internal fun IoBuffer.parseMessageFace(): Face {
//00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0 //00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0
//00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D //00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D
discardExact(1) discardExact(1)
...@@ -14,30 +14,30 @@ internal fun ByteArray.parseMessageFace(): Face = read { ...@@ -14,30 +14,30 @@ internal fun ByteArray.parseMessageFace(): Face = read {
val id1 = FaceID.ofId(readLVNumber().toInt().toUByte())//可能这个是id, 也可能下面那个 val id1 = FaceID.ofId(readLVNumber().toInt().toUByte())//可能这个是id, 也可能下面那个
discardExact(readByte().toLong()) discardExact(readByte().toLong())
readLVNumber()//某id? readLVNumber()//某id?
return@read Face(id1) return Face(id1)
} }
internal fun ByteArray.parsePlainText(): PlainText = read { internal fun IoBuffer.parsePlainText(): PlainText {
discardExact(1) discardExact(1)
PlainText(readLVString()) return PlainText(readLVString())
} }
internal fun ByteArray.parseMessageImage0x06(): Image = read { internal fun IoBuffer.parseMessageImage0x06(): Image {
discardExact(1) discardExact(1)
MiraiLogger.logDebug("好友的图片") this.debugPrint("好友的图片")
MiraiLogger.logDebug(this@parseMessageImage0x06.toUHexString()) //MiraiLogger.logDebug(this.toUHexString())
val filenameLength = readShort() val filenameLength = readShort()
val suffix = readString(filenameLength).substringAfter(".") val suffix = readString(filenameLength).substringAfter(".")
discardExact(this@parseMessageImage0x06.size - 37 - 1 - filenameLength - 2) discardExact(this@parseMessageImage0x06.readRemaining - 37 - 1 - filenameLength - 2)
val imageId = readString(36) val imageId = readString(36)
MiraiLogger.logDebug(imageId) MiraiLogger.logDebug(imageId)
discardExact(1)//0x41 discardExact(1)//0x41
return@read Image("{$imageId}.$suffix") return Image("{$imageId}.$suffix")
} }
internal fun ByteArray.parseMessageImage0x03(): Image = read { internal fun IoBuffer.parseMessageImage0x03(): Image {
discardExact(1) discardExact(1)
return@read Image(String(readLVByteArray())) return Image(String(readLVByteArray()))
/* /*
println(String(readLVByteArray())) println(String(readLVByteArray()))
readTLVMap() readTLVMap()
...@@ -53,14 +53,14 @@ internal fun ByteArray.parseMessageImage0x03(): Image = read { ...@@ -53,14 +53,14 @@ internal fun ByteArray.parseMessageImage0x03(): Image = read {
return Image(imageId)*/ return Image(imageId)*/
} }
internal fun ByteArray.parseMessageChain(): MessageChain = read { internal fun ByteReadPacket.parseMessageChain(): MessageChain {
readMessageChain() return readMessageChain()
} }
internal fun ByteReadPacket.readMessage(): Message? { internal fun ByteReadPacket.readMessage(): Message? {
val messageType = this.readByte().toInt() val messageType = this.readByte().toInt()
val sectionLength = this.readShort().toLong()//sectionLength: short val sectionLength = this.readShort().toLong()//sectionLength: short
val sectionData = this.readBytes(sectionLength.toInt())//use buffer instead val sectionData = this.readIoBuffer(sectionLength.toInt())//use buffer instead
return when (messageType) { return when (messageType) {
0x01 -> sectionData.parsePlainText() 0x01 -> sectionData.parsePlainText()
0x02 -> sectionData.parseMessageFace() 0x02 -> sectionData.parseMessageFace()
...@@ -68,7 +68,12 @@ internal fun ByteReadPacket.readMessage(): Message? { ...@@ -68,7 +68,12 @@ internal fun ByteReadPacket.readMessage(): Message? {
0x06 -> sectionData.parseMessageImage0x06() 0x06 -> sectionData.parseMessageImage0x06()
0x19 -> {//长文本 0x19 -> {//未知, 可能是长文本?
//bot手机自己跟自己发消息会出这个
//sectionData: 01 00 1C AA 02 19 08 00 88 01 00 9A 01 11 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00
sectionData.readBytes().debugPrint("sectionData")
return PlainText("[UNKNOWN(${this.readBytes().toUHexString()})]")
println()
val value = readLVByteArray() val value = readLVByteArray()
//todo 未知压缩算法 //todo 未知压缩算法
PlainText(String(value)) PlainText(String(value))
...@@ -87,7 +92,6 @@ internal fun ByteReadPacket.readMessage(): Message? { ...@@ -87,7 +92,6 @@ internal fun ByteReadPacket.readMessage(): Message? {
} }
0x0E -> { 0x0E -> {
//null
null null
} }
...@@ -102,16 +106,11 @@ internal fun ByteReadPacket.readMessage(): Message? { ...@@ -102,16 +106,11 @@ internal fun ByteReadPacket.readMessage(): Message? {
fun ByteReadPacket.readMessageChain(): MessageChain { fun ByteReadPacket.readMessageChain(): MessageChain {
val chain = MessageChain() val chain = MessageChain()
var got: Message? = null
do { do {
if (got != null) {
chain.concat(got)
}
if (this.remaining == 0L) { if (this.remaining == 0L) {
return chain return chain
} }
got = this.readMessage() } while (this.readMessage().takeIf { it != null }?.let { chain.concat(it) } != null)
} while (got != null)
return chain return chain
} }
......
...@@ -45,22 +45,14 @@ interface BotNetworkHandler<Socket : DataPacketSocket> : Closeable { ...@@ -45,22 +45,14 @@ interface BotNetworkHandler<Socket : DataPacketSocket> : Closeable {
var socket: Socket var socket: Socket
/** /**
* 事件处理. 如发送好友消息, 接受群消息并触发事件 * 得到 [PacketHandler].
* `get(EventPacketHandler)` 返回 [EventPacketHandler]
* `get(ActionPacketHandler)` 返回 [ActionPacketHandler]
*/ */
val event: EventPacketHandler operator fun <T : PacketHandler> get(key: PacketHandler.Key<T>): T
/** /**
* 动作处理. 如发送好友请求, 处理别人发来的好友请求等 * 依次尝试登录到可用的服务器. 在任一服务器登录完成后返回登录结果
*/
val action: ActionPacketHandler
/**
* [PacketHandler] 列表
*/
val packetHandlers: PacketHandlerList
/**
* 尝试登录. 将会依次尝试登录到可用的服务器. 在任一服务器登录完成后返回登录结果
*/ */
suspend fun login(configuration: LoginConfiguration): LoginResult suspend fun login(configuration: LoginConfiguration): LoginResult
......
...@@ -24,24 +24,19 @@ import net.mamoe.mirai.utils.* ...@@ -24,24 +24,19 @@ import net.mamoe.mirai.utils.*
* *
* @see BotNetworkHandler * @see BotNetworkHandler
*/ */
internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocket> { internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TIMBotNetworkHandler.BotSocket>, PacketHandlerList() {
override val NetworkScope: CoroutineScope = CoroutineScope(Dispatchers.Default) override val NetworkScope: CoroutineScope = CoroutineScope(Dispatchers.Default)
override lateinit var socket: BotSocket override lateinit var socket: BotSocket
override lateinit var event: EventPacketHandler
override lateinit var action: ActionPacketHandler
override val packetHandlers: PacketHandlerList = PacketHandlerList()
internal val temporaryPacketHandlers = mutableListOf<TemporaryPacketHandler<*>>() internal val temporaryPacketHandlers = mutableListOf<TemporaryPacketHandler<*>>()
private var heartbeatJob: Job? = null private var heartbeatJob: Job? = null
override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*>) { override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*>) {
temporaryPacketHandlers.add(temporaryPacketHandler) temporaryPacketHandlers.add(temporaryPacketHandler)
temporaryPacketHandler.send(action.session) temporaryPacketHandler.send(this[ActionPacketHandler].session)
} }
override suspend fun login(configuration: LoginConfiguration): LoginResult { override suspend fun login(configuration: LoginConfiguration): LoginResult {
...@@ -68,13 +63,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -68,13 +63,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
//private | internal //private | internal
private fun onLoggedIn(sessionKey: ByteArray) { private fun onLoggedIn(sessionKey: ByteArray) {
require(packetHandlers.size == 0) { "Already logged in" } require(size == 0) { "Already logged in" }
val session = LoginSession(bot, sessionKey, socket, NetworkScope) val session = LoginSession(bot, sessionKey, socket, NetworkScope)
event = EventPacketHandler(session)
action = ActionPacketHandler(session)
packetHandlers.add(event.asNode()) add(EventPacketHandler(session).asNode(EventPacketHandler))
packetHandlers.add(action.asNode()) add(ActionPacketHandler(session).asNode(ActionPacketHandler))
} }
private lateinit var sessionKey: ByteArray private lateinit var sessionKey: ByteArray
...@@ -89,7 +82,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -89,7 +82,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
this.loginResult.cancel(CancellationException("socket closed")) this.loginResult.cancel(CancellationException("socket closed"))
} }
this.packetHandlers.forEach { this.forEach {
it.instance.close() it.instance.close()
} }
...@@ -177,21 +170,14 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -177,21 +170,14 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
packet.use { packet.use {
//coz removeIf is not inline //coz removeIf is not inline
with(temporaryPacketHandlers.iterator()) { temporaryPacketHandlers.removeIfInlined {
while (hasNext()) { it.onPacketReceived(this@TIMBotNetworkHandler[ActionPacketHandler].session, packet)
if (next().onPacketReceived(action.session, packet)) {
remove()
} }
}
};
//For logDebug
{
val name = packet::class.simpleName val name = packet::class.simpleName
if (name != null && !name.endsWith("Encrypted") && !name.endsWith("Raw")) { if (name != null && !name.endsWith("Encrypted") && !name.endsWith("Raw")) {
bot.cyan("Packet received: $packet") bot.cyan("Packet received: $packet")
} }
}()
if (packet is ServerEventPacket) { if (packet is ServerEventPacket) {
//no need to sync acknowledgement packets //no need to sync acknowledgement packets
...@@ -205,7 +191,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -205,7 +191,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
} }
loginHandler.onPacketReceived(packet) loginHandler.onPacketReceived(packet)
packetHandlers.forEach { this@TIMBotNetworkHandler.forEach {
it.instance.onPacketReceived(packet) it.instance.onPacketReceived(packet)
} }
} }
...@@ -223,7 +209,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -223,7 +209,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
try { try {
build.readAvailable(buffer) build.readAvailable(buffer)
channel.send(buffer)//JVM: withContext(IO) channel.send(buffer)//JVM: withContext(IO)
} catch (e: Exception) { } catch (e: SendPacketInternalException) {
bot.logger.logError("Caught SendPacketInternalException: ${e.cause?.message}")
bot.reinitializeNetworkHandler(configuration)
return@withContext
} catch (e: Throwable) {
e.log() e.log()
return@withContext return@withContext
} finally { } finally {
...@@ -379,7 +369,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI ...@@ -379,7 +369,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler<TI
//登录成功后会收到大量上次的消息, 忽略掉 todo 优化 //登录成功后会收到大量上次的消息, 忽略掉 todo 优化
NetworkScope.launch { NetworkScope.launch {
delay(3000) delay(3000)
event.ignoreMessage = false this@TIMBotNetworkHandler[EventPacketHandler].ignoreMessage = false
} }
onLoggedIn(sessionKey) onLoggedIn(sessionKey)
......
...@@ -23,6 +23,8 @@ import net.mamoe.mirai.utils.hexToBytes ...@@ -23,6 +23,8 @@ import net.mamoe.mirai.utils.hexToBytes
* @author Him188moe * @author Him188moe
*/ */
class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
companion object Key : PacketHandler.Key<ActionPacketHandler>
private val addFriendSessions = mutableListOf<AddFriendSession>() private val addFriendSessions = mutableListOf<AddFriendSession>()
private val uploadImageSessions = mutableListOf<UploadImageSession>() private val uploadImageSessions = mutableListOf<UploadImageSession>()
......
...@@ -24,6 +24,9 @@ import net.mamoe.mirai.utils.MiraiLogger ...@@ -24,6 +24,9 @@ import net.mamoe.mirai.utils.MiraiLogger
*/ */
@Suppress("EXPERIMENTAL_API_USAGE") @Suppress("EXPERIMENTAL_API_USAGE")
class EventPacketHandler(session: LoginSession) : PacketHandler(session) { class EventPacketHandler(session: LoginSession) : PacketHandler(session) {
companion object Key : PacketHandler.Key<EventPacketHandler>
internal var ignoreMessage: Boolean = true internal var ignoreMessage: Boolean = true
override suspend fun onPacketReceived(packet: ServerPacket): Unit = with(session) { override suspend fun onPacketReceived(packet: ServerPacket): Unit = with(session) {
...@@ -57,6 +60,16 @@ class EventPacketHandler(session: LoginSession) : PacketHandler(session) { ...@@ -57,6 +60,16 @@ class EventPacketHandler(session: LoginSession) : PacketHandler(session) {
//TODO //TODO
} }
is ServerFriendTypingStartedPacket -> {
MiraiLogger.logInfo("${packet.qq.toLong()} 正在输入")
//TODO
}
is ServerFriendTypingCanceledPacket -> {
MiraiLogger.logInfo("${packet.qq.toLong()} 取消了输入")
//TODO
}
else -> { else -> {
//ignored //ignored
} }
......
...@@ -12,6 +12,8 @@ abstract class PacketHandler( ...@@ -12,6 +12,8 @@ abstract class PacketHandler(
) { ) {
abstract suspend fun onPacketReceived(packet: ServerPacket) abstract suspend fun onPacketReceived(packet: ServerPacket)
interface Key<T : PacketHandler>
open fun close() { open fun close() {
} }
...@@ -19,15 +21,18 @@ abstract class PacketHandler( ...@@ -19,15 +21,18 @@ abstract class PacketHandler(
class PacketHandlerNode<T : PacketHandler>( class PacketHandlerNode<T : PacketHandler>(
val clazz: KClass<T>, val clazz: KClass<T>,
val instance: T val instance: T,
val key: PacketHandler.Key<T>
) )
fun <T : PacketHandler> T.asNode(): PacketHandlerNode<T> { fun <T : PacketHandler> T.asNode(key: PacketHandler.Key<T>): PacketHandlerNode<T> {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return PacketHandlerNode(this::class as KClass<T>, this) return PacketHandlerNode(this::class as KClass<T>, this, key)
} }
class PacketHandlerList : MutableList<PacketHandlerNode<*>> by mutableListOf() { open class PacketHandlerList : MutableList<PacketHandlerNode<*>> by mutableListOf() {
@Suppress("UNCHECKED_CAST")
operator fun <T : PacketHandler> get(key: PacketHandler.Key<T>): T = this.first { it.key === key }.instance as T
operator fun <T : PacketHandler> get(clazz: KClass<T>): T { operator fun <T : PacketHandler> get(clazz: KClass<T>): T {
this.forEach { this.forEach {
......
...@@ -18,12 +18,12 @@ class ClientSendFriendMessagePacket( ...@@ -18,12 +18,12 @@ class ClientSendFriendMessagePacket(
private val message: MessageChain private val message: MessageChain
) : ClientPacket() { ) : ClientPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) { override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeRandom(2) writeRandom(2)
this.writeQQ(botQQ) writeQQ(botQQ)
this.writeHex(TIMProtocol.fixVer2) writeHex(TIMProtocol.fixVer2)
this.encryptAndWrite(sessionKey) { encryptAndWrite(sessionKey) {
writeQQ(botQQ) writeQQ(botQQ)
writeQQ(targetQQ) writeQQ(targetQQ)
writeHex("00 00 00 08 00 01 00 04 00 00 00 00") writeHex("00 00 00 08 00 01 00 04 00 00 00 00")
......
...@@ -86,7 +86,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {//TODO 优化 ...@@ -86,7 +86,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {//TODO 优化
"00 BA" -> ServerCaptchaPacket.Encrypted(this, idHex) "00 BA" -> ServerCaptchaPacket.Encrypted(this, idHex)
"00 CE", "00 17" -> ServerEventPacket.Raw.Encrypted(this, idHex.hexToBytes()) "00 CE", "00 17" -> ServerEventPacket.Raw.Encrypted(this)
"00 81" -> ServerFieldOnlineStatusChangedPacket.Encrypted(this) "00 81" -> ServerFieldOnlineStatusChangedPacket.Encrypted(this)
...@@ -102,7 +102,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {//TODO 优化 ...@@ -102,7 +102,7 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {//TODO 优化
}.setId(idHex) }.setId(idHex)
} }
fun ByteReadPacket.readIP(): String = buildString(4 + 3) { fun Input.readIP(): String = buildString(4 + 3) {
repeat(4) { repeat(4) {
val byte = readUByte() val byte = readUByte()
this.append(byte.toString()) this.append(byte.toString())
...@@ -110,11 +110,11 @@ fun ByteReadPacket.readIP(): String = buildString(4 + 3) { ...@@ -110,11 +110,11 @@ fun ByteReadPacket.readIP(): String = buildString(4 + 3) {
} }
} }
fun ByteReadPacket.readLVString(): String = String(this.readLVByteArray()) fun Input.readLVString(): String = String(this.readLVByteArray())
fun ByteReadPacket.readLVByteArray(): ByteArray = this.readBytes(this.readShort().toInt()) fun Input.readLVByteArray(): ByteArray = this.readBytes(this.readShort().toInt())
fun ByteReadPacket.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray> { fun Input.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray> {
val map = mutableMapOf<Int, ByteArray>() val map = mutableMapOf<Int, ByteArray>()
var type: UByte var type: UByte
...@@ -144,11 +144,11 @@ fun ByteReadPacket.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray ...@@ -144,11 +144,11 @@ fun ByteReadPacket.readTLVMap(expectingEOF: Boolean = false): Map<Int, ByteArray
fun Map<Int, ByteArray>.printTLVMap(name: String) = debugPrintln("TLVMap $name= " + this.mapValues { (_, value) -> value.toUHexString() }) fun Map<Int, ByteArray>.printTLVMap(name: String) = debugPrintln("TLVMap $name= " + this.mapValues { (_, value) -> value.toUHexString() })
fun ByteReadPacket.readString(length: Number): String = String(this.readBytes(length.toInt())) fun Input.readString(length: Number): String = String(this.readBytes(length.toInt()))
private const val TRUE_BYTE_VALUE: Byte = 1 private const val TRUE_BYTE_VALUE: Byte = 1
fun ByteReadPacket.readBoolean(): Boolean = this.readByte() == TRUE_BYTE_VALUE fun Input.readBoolean(): Boolean = this.readByte() == TRUE_BYTE_VALUE
fun ByteReadPacket.readLVNumber(): Number { fun Input.readLVNumber(): Number {
return when (this.readShort().toInt()) { return when (this.readShort().toInt()) {
1 -> this.readByte() 1 -> this.readByte()
2 -> this.readShort() 2 -> this.readShort()
...@@ -161,7 +161,7 @@ fun ByteReadPacket.readLVNumber(): Number { ...@@ -161,7 +161,7 @@ fun ByteReadPacket.readLVNumber(): Number {
//添加@JvmSynthetic 导致 idea 无法检查这个文件的错误 //添加@JvmSynthetic 导致 idea 无法检查这个文件的错误
//@JvmSynthetic //@JvmSynthetic
@Deprecated("Low efficiency", ReplaceWith("")) @Deprecated("Low efficiency", ReplaceWith(""))
fun ByteReadPacket.gotoWhere(matcher: UByteArray): ByteReadPacket { fun <I : Input> I.gotoWhere(matcher: UByteArray): I {
return this.gotoWhere(matcher.toByteArray()) return this.gotoWhere(matcher.toByteArray())
} }
...@@ -169,7 +169,7 @@ fun ByteReadPacket.gotoWhere(matcher: UByteArray): ByteReadPacket { ...@@ -169,7 +169,7 @@ fun ByteReadPacket.gotoWhere(matcher: UByteArray): ByteReadPacket {
* 去往下一个含这些连续字节的位置 * 去往下一个含这些连续字节的位置
*/ */
@Deprecated("Low efficiency", ReplaceWith("")) @Deprecated("Low efficiency", ReplaceWith(""))
fun ByteReadPacket.gotoWhere(matcher: ByteArray): ByteReadPacket { fun <I : Input> I.gotoWhere(matcher: ByteArray): I {
require(matcher.isNotEmpty()) require(matcher.isNotEmpty())
loop@ loop@
......
package net.mamoe.mirai.utils package net.mamoe.mirai.utils
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Input import kotlinx.io.core.Input
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
...@@ -9,20 +10,26 @@ internal object DebugLogger : MiraiLogger by PlatformLogger("Packet Debug") ...@@ -9,20 +10,26 @@ internal object DebugLogger : MiraiLogger by PlatformLogger("Packet Debug")
internal fun debugPrintln(any: Any?) = DebugLogger.logPurple(any) internal fun debugPrintln(any: Any?) = DebugLogger.logPurple(any)
@Deprecated("Debugging Warning", ReplaceWith(""))
internal fun ByteArray.debugPrint(name: String): ByteArray { internal fun ByteArray.debugPrint(name: String): ByteArray {
DebugLogger.logPurple(name + "=" + this.toUHexString()) DebugLogger.logPurple(name + "=" + this.toUHexString())
return this return this
} }
@Deprecated("Debugging Warning", ReplaceWith("")) @Deprecated("Low Efficiency", ReplaceWith(""))
internal fun IoBuffer.debugPrint(name: String): IoBuffer { internal fun IoBuffer.debugPrint(name: String): IoBuffer {
val readBytes = this.readBytes() val readBytes = this.readBytes()
DebugLogger.logPurple(name + "=" + readBytes.toUHexString()) DebugLogger.logPurple(name + "=" + readBytes.toUHexString())
return readBytes.toIoBuffer() return readBytes.toIoBuffer()
} }
@Deprecated("Debugging Warning", ReplaceWith("")) @Deprecated("Low Efficiency", ReplaceWith("discardExact(n)"))
internal fun Input.debugDiscardExact(n: Number, name: String = "") { internal fun Input.debugDiscardExact(n: Number, name: String = "") {
DebugLogger.logPurple("Discarded($n) $name=" + this.readBytes(n.toInt()).toUHexString()) DebugLogger.logPurple("Discarded($n) $name=" + this.readBytes(n.toInt()).toUHexString())
} }
@Deprecated("Low Efficiency", ReplaceWith(""))
internal fun ByteReadPacket.debugPrint(name: String = ""): ByteReadPacket {
val bytes = this.readBytes()
DebugLogger.logPurple("ByteReadPacket $name=" + bytes.toUHexString())
return bytes.toReadPacket()
}
...@@ -12,3 +12,5 @@ expect class MiraiDatagramChannel(serverHost: String, serverPort: Short) : Close ...@@ -12,3 +12,5 @@ expect class MiraiDatagramChannel(serverHost: String, serverPort: Short) : Close
} }
expect class ClosedChannelException : IOException expect class ClosedChannelException : IOException
expect class SendPacketInternalException(cause: Throwable?) : Exception
\ No newline at end of file
...@@ -14,7 +14,15 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP ...@@ -14,7 +14,15 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP
private val channel: DatagramChannel = DatagramChannel.open().connect(serverAddress) private val channel: DatagramChannel = DatagramChannel.open().connect(serverAddress)
actual suspend fun read(buffer: IoBuffer) = withContext(Dispatchers.IO) { (channel as ReadableByteChannel).read(buffer) } actual suspend fun read(buffer: IoBuffer) = withContext(Dispatchers.IO) { (channel as ReadableByteChannel).read(buffer) }
actual suspend fun send(buffer: IoBuffer) = withContext(Dispatchers.IO) { buffer.readDirect { channel.send(it, serverAddress) } } actual suspend fun send(buffer: IoBuffer) = withContext(Dispatchers.IO) {
buffer.readDirect {
try {
channel.send(it, serverAddress)
} catch (e: Exception) {
throw SendPacketInternalException(e)
}
}
}
override fun close() { override fun close() {
channel.close() channel.close()
...@@ -24,3 +32,5 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP ...@@ -24,3 +32,5 @@ actual class MiraiDatagramChannel actual constructor(serverHost: String, serverP
} }
actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException actual typealias ClosedChannelException = java.nio.channels.ClosedChannelException
actual class SendPacketInternalException actual constructor(cause: Throwable?) : Exception(cause)
\ No newline at end of file
...@@ -20,14 +20,10 @@ import kotlin.math.max ...@@ -20,14 +20,10 @@ import kotlin.math.max
object HexComparator { object HexComparator {
private val RED = "\u001b[31m" private val RED = "\u001b[31m"
private val GREEN = "\u001b[33m" private val GREEN = "\u001b[33m"
private val UNKNOWN = "\u001b[30m" private val UNKNOWN = "\u001b[30m"
private val BLUE = "\u001b[34m" private val BLUE = "\u001b[34m"
private val clipboardString: String? private val clipboardString: String?
get() { get() {
val trans = Toolkit.getDefaultToolkit().systemClipboard.getContents(null) val trans = Toolkit.getDefaultToolkit().systemClipboard.getContents(null)
...@@ -44,7 +40,6 @@ object HexComparator { ...@@ -44,7 +40,6 @@ object HexComparator {
} }
class ConstMatcher constructor(hex: String) { class ConstMatcher constructor(hex: String) {
private val matches = LinkedList<Match>() private val matches = LinkedList<Match>()
object TestConsts { object TestConsts {
...@@ -59,6 +54,7 @@ object HexComparator { ...@@ -59,6 +54,7 @@ object HexComparator {
val _Him188moe_ = "Him188moe".toByteArray().toUHexString() val _Him188moe_ = "Him188moe".toByteArray().toUHexString()
val 发图片 = "发图片".toByteArray().toUHexString() val 发图片 = "发图片".toByteArray().toUHexString()
val 群 = "群".toByteArray().toUHexString() val 群 = "群".toByteArray().toUHexString()
val 你好 = "你好".toByteArray().toUHexString()
val SINGLE_PLAIN_MESSAGE_HEAD = "00 00 01 00 09 01" val SINGLE_PLAIN_MESSAGE_HEAD = "00 00 01 00 09 01"
...@@ -69,7 +65,8 @@ object HexComparator { ...@@ -69,7 +65,8 @@ object HexComparator {
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
object PacketIds { object PacketIds {
val heartbeat = "00 58" val heartbeat = "00 58"
val friendmsg = "00 CD" val friendmsgsend = "00 CD"
val friendmsgevent = "00 CE"
} }
init { init {
...@@ -104,7 +101,6 @@ object HexComparator { ...@@ -104,7 +101,6 @@ object HexComparator {
} }
} }
private fun match(hex: String, field: Field): List<IntRange> { private fun match(hex: String, field: Field): List<IntRange> {
val constValue: String val constValue: String
try { try {
...@@ -293,6 +289,10 @@ object HexComparator { ...@@ -293,6 +289,10 @@ object HexComparator {
} }
fun main() { fun main() {
// println(HexComparator.colorize("00 00 00 25 00 08 00 02 00 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 01 38 03 3E 03 3F A2 76 E4 B8 DD E7 86 74 F2 64 55 AD 9A EB 2F B9 DF F1 7F 8C 28 00 0B 78 14 5D A2 F5 CB 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D A2 F5 CA 9D 26 CB 5E 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E4 BD A0 E5 A5 BD 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00"))
val scanner = Scanner(System.`in`) val scanner = Scanner(System.`in`)
while (true) { while (true) {
println("Hex1: ") println("Hex1: ")
......
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