From 4f4bc05da652bfb9132e10618e52477681e599d7 Mon Sep 17 00:00:00 2001 From: Him188moe Date: Thu, 19 Sep 2019 22:11:57 +0800 Subject: [PATCH] Kotlin coroutine --- .../java/net/mamoe/mirai/contact/Contact.kt | 8 +-- .../java/net/mamoe/mirai/contact/Group.kt | 2 +- .../main/java/net/mamoe/mirai/contact/QQ.kt | 2 +- .../mirai/message/defaults/UnsolvedImage.kt | 2 +- .../mirai/network/BotNetworkHandlerImpl.kt | 41 ++++++----- .../net/mamoe/mirai/network/NetworkScope.kt | 21 ++++++ .../network/handler/ActionPacketHandler.kt | 19 ++--- .../mirai/network/handler/DataPacketSocket.kt | 19 +---- .../network/handler/MessagePacketHandler.kt | 72 ++++++++++--------- .../mirai/network/handler/PacketHandler.kt | 2 +- .../network/handler/TemporaryPacketHandler.kt | 2 +- .../net/mamoe/mirai/utils/BotAccount.java | 4 +- mirai-core/src/test/java/PacketDebuger.kt | 2 +- 13 files changed, 108 insertions(+), 88 deletions(-) create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/NetworkScope.kt diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt index f26f7cfc5..d20117042 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt @@ -21,23 +21,23 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) { /** * Async */ - abstract fun sendMessage(message: MessageChain) + abstract suspend fun sendMessage(message: MessageChain) /** * 上传图片 */ - fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture { + suspend fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture { return image.upload(session, this) } - fun sendMessage(message: Message) { + suspend fun sendMessage(message: Message) { if (message is MessageChain) { return sendMessage(message) } return sendMessage(message.toChain()) } - fun sendMessage(message: String) { + suspend fun sendMessage(message: String) { this.sendMessage(PlainText(message)) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt index deea82b8c..2bac93e3b 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt @@ -25,7 +25,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number), Closeable { val groupId = groupNumberToId(number) val members = ContactList() - override fun sendMessage(message: MessageChain) { + override suspend fun sendMessage(message: MessageChain) { bot.network.message.sendGroupMessage(this, message) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt index 0fd755d0f..e9eb227c3 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt @@ -18,7 +18,7 @@ import net.mamoe.mirai.message.defaults.MessageChain * @author Him188moe */ class QQ(bot: Bot, number: Long) : Contact(bot, number) { - override fun sendMessage(message: MessageChain) { + override suspend fun sendMessage(message: MessageChain) { bot.network.message.sendFriendMessage(this, message) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt index b3cf226b9..16fd75eb5 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt @@ -26,7 +26,7 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage constructor(imageFile: File) : this(imageFile.name, ImageIO.read(imageFile)) constructor(url: URL) : this(File(url.file)) - fun upload(session: LoginSession, contact: Contact): CompletableFuture { + suspend fun upload(session: LoginSession, contact: Contact): CompletableFuture {//todo be suspend return session.expectPacket { toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandlerImpl.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandlerImpl.kt index e0887ba44..59a767623 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandlerImpl.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandlerImpl.kt @@ -1,5 +1,6 @@ package net.mamoe.mirai.network +import kotlinx.coroutines.* import net.mamoe.mirai.Bot import net.mamoe.mirai.MiraiServer import net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent @@ -40,8 +41,11 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { internal val temporaryPacketHandlers = Collections.synchronizedList(mutableListOf>()) + override fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*>) { - temporaryPacketHandler.send(action.session) + runBlocking { + temporaryPacketHandler.send(action.session) + } temporaryPacketHandlers.add(temporaryPacketHandler) } @@ -95,7 +99,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { internal inner class BotSocket : Closeable, DataPacketSocket { - override fun distributePacket(packet: ServerPacket) { + override suspend fun distributePacket(packet: ServerPacket) { try { packet.decode() } catch (e: java.lang.Exception) { @@ -150,12 +154,8 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { val packet = DatagramPacket(ByteArray(2048), 2048) kotlin.runCatching { socket?.receive(packet) } .onSuccess { - MiraiThreadPool.getInstance().submit { - try { - distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail())) - } catch (e: Exception) { - e.printStackTrace() - } + GlobalScope.launch { + distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail())) } }.onFailure { if (it.message == "Socket closed" || it.message == "socket closed") { @@ -184,7 +184,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { bot.waitForPacket(ServerPacket::class, timeoutMillis) { loginFuture!!.complete(LoginState.TIMEOUT) } - sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP)) + runBlocking { + sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP)) + } return this.loginFuture!! } @@ -193,8 +195,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { * Not async */ @Synchronized - - override fun sendPacket(packet: ClientPacket) { + override suspend fun sendPacket(packet: ClientPacket) { checkNotNull(socket) { "network closed" } if (socket!!.isClosed) { return @@ -208,7 +209,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { } val data = packet.toByteArray() - socket!!.send(DatagramPacket(data, data.size)) + withContext(Dispatchers.IO) { + socket!!.send(DatagramPacket(data, data.size)) + } bot.cyanL("Packet sent: $packet") PacketSentEvent(bot, packet).broadcast() @@ -255,7 +258,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { private var heartbeatFuture: ScheduledFuture<*>? = null - fun onPacketReceived(packet: ServerPacket) { + suspend fun onPacketReceived(packet: ServerPacket) { when (packet) { is ServerTouchResponsePacket -> { if (packet.serverIP != null) {//redirection @@ -304,7 +307,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { this.token00BA = packet.token00BA if (packet.transmissionCompleted) { - bot.notice(CharImageUtil.createCharImg(ImageIO.read(this.captchaCache!!.inputStream()))) + withContext(Dispatchers.IO) { + bot.notice(CharImageUtil.createCharImg(ImageIO.read(captchaCache!!.inputStream()))) + } bot.notice("需要验证码登录, 验证码为 4 字母") try { (MiraiServer.getInstance().parentFolder + "VerificationCode.png").writeBytes(this.captchaCache!!) @@ -350,7 +355,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { is ServerSessionKeyResponsePacket -> { sessionKey = packet.sessionKey heartbeatFuture = MiraiThreadPool.getInstance().scheduleWithFixedDelay({ - socket.sendPacket(ClientHeartbeatPacket(bot.account.qqNumber, sessionKey)) + runBlocking { + socket.sendPacket(ClientHeartbeatPacket(bot.account.qqNumber, sessionKey)) + } }, 90000, 90000, TimeUnit.MILLISECONDS) socket.loginFuture!!.complete(LoginState.SUCCESS) @@ -390,7 +397,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler { } fun changeOnlineStatus(status: ClientLoginStatus) { - socket.sendPacket(ClientChangeOnlineStatusPacket(bot.account.qqNumber, sessionKey, status)) + NetworkScope.launch { + socket.sendPacket(ClientChangeOnlineStatusPacket(bot.account.qqNumber, sessionKey, status)) + } } override fun close() { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/NetworkScope.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/NetworkScope.kt new file mode 100644 index 000000000..3e537ce18 --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/NetworkScope.kt @@ -0,0 +1,21 @@ +package net.mamoe.mirai.network + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.asCoroutineDispatcher +import java.util.concurrent.SynchronousQueue +import java.util.concurrent.ThreadPoolExecutor +import java.util.concurrent.TimeUnit +import kotlin.coroutines.CoroutineContext + +object NetworkScope : CoroutineScope { + override val coroutineContext: CoroutineContext + get() = lazy { + ThreadPoolExecutor( + 1, + 4, + 8000, TimeUnit.MILLISECONDS, + SynchronousQueue() + ).asCoroutineDispatcher() + }.value//todo improve + +} \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt index 68e804e9c..45be2e2d8 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt @@ -1,5 +1,6 @@ package net.mamoe.mirai.network.handler +import kotlinx.coroutines.runBlocking import net.mamoe.mirai.network.LoginSession import net.mamoe.mirai.network.packet.* import net.mamoe.mirai.network.packet.action.AddFriendResult @@ -32,7 +33,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { private var sKeyRefresherFuture: ScheduledFuture<*>? = null - override fun onPacketReceived(packet: ServerPacket) { + override suspend fun onPacketReceived(packet: ServerPacket) { when (packet) { is ServerCanAddFriendResponsePacket -> { this.uploadImageSessions.forEach { @@ -60,7 +61,9 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { session.cookies = "uin=o" + session.bot.account.qqNumber + ";skey=" + session.sKey + ";" sKeyRefresherFuture = MiraiThreadPool.getInstance().scheduleWithFixedDelay({ - session.socket.sendPacket(ClientSKeyRefreshmentRequestPacket(session.bot.account.qqNumber, session.sessionKey)) + runBlocking { + session.socket.sendPacket(ClientSKeyRefreshmentRequestPacket(session.bot.account.qqNumber, session.sessionKey)) + } }, 1800000, 1800000, TimeUnit.MILLISECONDS) session.gtk = getGTK(session.sKey) @@ -75,13 +78,13 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { } - fun addFriend(qqNumber: Long, message: Supplier) { + suspend fun addFriend(qqNumber: Long, message: Supplier) { addFriend(qqNumber, lazy { message.get() }) } @JvmSynthetic - fun addFriend(qqNumber: Long, message: Lazy = lazyOf("")): CompletableFuture { + suspend fun addFriend(qqNumber: Long, message: Lazy = lazyOf("")): CompletableFuture { val future = CompletableFuture() val session = AddFriendSession(qqNumber, future, message) // uploadImageSessions.add(session) @@ -90,12 +93,12 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { } - fun requestSKey() { + suspend fun requestSKey() { session.socket.sendPacket(ClientSKeyRequestPacket(session.bot.account.qqNumber, session.sessionKey)) } - fun requestAccountInfo() { + suspend fun requestAccountInfo() { session.socket.sendPacket(ClientAccountInfoRequestPacket(session.bot.account.qqNumber, session.sessionKey)) } @@ -165,7 +168,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { lateinit var id: ByteArray - fun onPacketReceived(packet: ServerPacket) { + suspend fun onPacketReceived(packet: ServerPacket) { if (!::id.isInitialized) { return } @@ -202,7 +205,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) { } - fun sendAddRequest() { + suspend fun sendAddRequest() { session.socket.sendPacket(ClientCanAddFriendPacket(session.bot.account.qqNumber, qq, session.sessionKey).also { this.id = it.packetIdLast }) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/DataPacketSocket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/DataPacketSocket.kt index 4eb19c20c..870373299 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/DataPacketSocket.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/DataPacketSocket.kt @@ -6,9 +6,7 @@ import net.mamoe.mirai.network.BotNetworkHandlerImpl import net.mamoe.mirai.network.LoginSession import net.mamoe.mirai.network.packet.ClientPacket import net.mamoe.mirai.network.packet.ServerPacket -import net.mamoe.mirai.task.MiraiThreadPool import java.io.Closeable -import java.util.concurrent.Future /** * 网络接口. @@ -23,7 +21,7 @@ interface DataPacketSocket : Closeable { /** * 分发数据包给 [PacketHandler] */ - fun distributePacket(packet: ServerPacket) + suspend fun distributePacket(packet: ServerPacket) /** * 发送一个数据包(非异步). @@ -32,20 +30,7 @@ interface DataPacketSocket : Closeable { * * @see [LoginSession.expectPacket] kotlin DSL */ - fun sendPacket(packet: ClientPacket) - - /** - * 发送一个数据包(异步). - * - * 可通过 hook 事件 [ServerPacketReceivedEvent] 来获取服务器返回. - * - * @see [LoginSession.expectPacket] kotlin DSL - */ - fun sendPacketAsync(packet: ClientPacket): Future<*> { - return MiraiThreadPool.getInstance().submit { - sendPacket(packet) - } - } + suspend fun sendPacket(packet: ClientPacket) fun isClosed(): Boolean diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt index 8a95cc32a..d55a57bfb 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt @@ -1,5 +1,6 @@ package net.mamoe.mirai.network.handler +import kotlinx.coroutines.runBlocking import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.event.events.group.GroupMessageEvent @@ -30,46 +31,49 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) { init { //todo for test FriendMessageEvent::class.hookWhile { - if (session.socket.isClosed()) { - return@hookWhile false - } - when { - it.message valueEquals "你好" -> it.sender.sendMessage("你好!") - it.message.toString().startsWith("复读") -> it.sender.sendMessage(it.message()) - it.message.toString().startsWith("发群") -> { - it.message().list.toMutableList().let { messages -> - messages.removeAt(0) - sendGroupMessage(Group(session.bot, 580266363), MessageChain(messages)) - } + return@hookWhile runBlocking { + if (session.socket.isClosed()) { + return@runBlocking false + } + when { + it.message valueEquals "你好" -> it.sender.sendMessage("你好!") + it.message.toString().startsWith("复读") -> it.sender.sendMessage(it.message()) + it.message.toString().startsWith("发群") -> { + it.message().list.toMutableList().let { messages -> + messages.removeAt(0) + sendGroupMessage(Group(session.bot, 580266363), MessageChain(messages)) + } + } + /*it.message valueEquals "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> + image.upload(session, Group(session.bot, 580266363)).get() + })*/ + it.message valueEquals "发图片群2" -> sendGroupMessage(Group(session.bot, 580266363), Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg").toChain()) + /* it.message valueEquals "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> + image.upload(session, it.sender).get() + })*/ + it.message valueEquals "发图片2" -> sendFriendMessage(it.sender, PlainText("test") + Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg")) } - /*it.message valueEquals "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> - image.upload(session, Group(session.bot, 580266363)).get() - })*/ - it.message valueEquals "发图片群2" -> sendGroupMessage(Group(session.bot, 580266363), Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg").toChain()) - /* it.message valueEquals "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> - image.upload(session, it.sender).get() - })*/ - it.message valueEquals "发图片2" -> sendFriendMessage(it.sender, PlainText("test") + Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg")) - } - return@hookWhile true + return@runBlocking true + } } GroupMessageEvent::class.hookWhile { - if (session.socket.isClosed()) { - return@hookWhile false + return@hookWhile runBlocking { + if (session.socket.isClosed()) { + return@runBlocking false + } + + when { + it.message.contains("复读") -> it.group.sendMessage(it.chain) + } + + return@runBlocking true } - - when { - it.message.contains("复读") -> it.group.sendMessage(it.chain) - } - - return@hookWhile true - } } - override fun onPacketReceived(packet: ServerPacket) { + override suspend fun onPacketReceived(packet: ServerPacket) { when (packet) { is ServerGroupUploadFileEventPacket -> { //todo @@ -99,11 +103,11 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) { } } - fun sendFriendMessage(qq: QQ, message: MessageChain) { - session.socket.sendPacketAsync(ClientSendFriendMessagePacket(session.bot.account.qqNumber, qq.number, session.sessionKey, message)) + suspend fun sendFriendMessage(qq: QQ, message: MessageChain) { + session.socket.sendPacket(ClientSendFriendMessagePacket(session.bot.account.qqNumber, qq.number, session.sessionKey, message)) } - fun sendGroupMessage(group: Group, message: MessageChain) { + suspend fun sendGroupMessage(group: Group, message: MessageChain) { session.socket.sendPacket(ClientSendGroupMessagePacket(session.bot.account.qqNumber, group.groupId, session.sessionKey, message)) } } \ No newline at end of file diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/PacketHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/PacketHandler.kt index 1ff85ce95..86c6bc21d 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/PacketHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/PacketHandler.kt @@ -11,7 +11,7 @@ import java.io.Closeable abstract class PacketHandler( val session: LoginSession ) : Closeable { - abstract fun onPacketReceived(packet: ServerPacket) + abstract suspend fun onPacketReceived(packet: ServerPacket) override fun close() { diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt index 3e6b06d95..566028bff 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt @@ -32,7 +32,7 @@ open class TemporaryPacketHandler

( this.expect = handler } - fun send(session: LoginSession) { + suspend fun send(session: LoginSession) { this.session = session session.socket.sendPacket(toSend) } diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/BotAccount.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/BotAccount.java index ef2dcefa3..5965a4178 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/utils/BotAccount.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/BotAccount.java @@ -6,8 +6,6 @@ import lombok.Data; @Data @AllArgsConstructor public class BotAccount { - public final long qqNumber; - private final String password; - + public final String password; } diff --git a/mirai-core/src/test/java/PacketDebuger.kt b/mirai-core/src/test/java/PacketDebuger.kt index 3caef2250..7457f45f6 100644 --- a/mirai-core/src/test/java/PacketDebuger.kt +++ b/mirai-core/src/test/java/PacketDebuger.kt @@ -40,7 +40,7 @@ object Main { println("-------------------------------------------") exitProcess(0)*/ - var jpcap: JpcapCaptor? = null + val jpcap: JpcapCaptor? val caplen = 4096 val promiscCheck = true