From 6ccd20c377eec647dc940b04b2dc2d85488ae637 Mon Sep 17 00:00:00 2001 From: Him188 Date: Thu, 17 Dec 2020 09:18:25 +0800 Subject: [PATCH] Simplify platform structure, simplify network implementations --- .../network/QQAndroidBotNetworkHandler.kt | 2 +- .../kotlin/network/QQAndroidClient.kt | 4 +- .../kotlin/network/highway/HighwayHelper.kt | 3 +- .../network/protocol/packet/EncryptMethod.kt | 4 +- .../network/protocol/packet/PacketFactory.kt | 4 +- .../network/protocol/packet/login/WtLogin.kt | 2 +- .../kotlin/utils/AtomicResizeCacheList.kt | 87 ------- ...mUtils.common.kt => MiraiPlatformUtils.kt} | 0 .../kotlin/utils/PlatformDatagramChannel.kt | 91 +++++++- .../commonMain/kotlin/utils/PlatformSocket.kt | 93 ++++++-- .../kotlin/utils/contentToString.kt | 4 +- .../kotlin/utils/{cryptor => crypto}/ECDH.kt | 6 +- .../kotlin/utils/{cryptor => crypto}/TEA.kt | 3 +- .../src/commonMain/kotlin/utils/io/output.kt | 4 +- .../jvmMain/kotlin/utils/PlatformSocket.kt | 212 ------------------ .../jvmMain/kotlin/utils/PlatformSocketJvm.kt | 104 --------- .../ECDHJvm.kt => crypto/ECDHJvmDesktop.kt} | 6 +- .../src/jvmMain/kotlin/utils/setVisible.kt | 17 -- 18 files changed, 174 insertions(+), 472 deletions(-) delete mode 100644 mirai-core/src/commonMain/kotlin/utils/AtomicResizeCacheList.kt rename mirai-core/src/commonMain/kotlin/utils/{MiraiPlatformUtils.common.kt => MiraiPlatformUtils.kt} (100%) rename mirai-core/src/commonMain/kotlin/utils/{cryptor => crypto}/ECDH.kt (96%) rename mirai-core/src/commonMain/kotlin/utils/{cryptor => crypto}/TEA.kt (99%) delete mode 100644 mirai-core/src/jvmMain/kotlin/utils/PlatformSocket.kt delete mode 100644 mirai-core/src/jvmMain/kotlin/utils/PlatformSocketJvm.kt rename mirai-core/src/jvmMain/kotlin/utils/{cryptor/ECDHJvm.kt => crypto/ECDHJvmDesktop.kt} (96%) delete mode 100644 mirai-core/src/jvmMain/kotlin/utils/setVisible.kt diff --git a/mirai-core/src/commonMain/kotlin/network/QQAndroidBotNetworkHandler.kt b/mirai-core/src/commonMain/kotlin/network/QQAndroidBotNetworkHandler.kt index 961566e79..0d91a9164 100644 --- a/mirai-core/src/commonMain/kotlin/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core/src/commonMain/kotlin/network/QQAndroidBotNetworkHandler.kt @@ -130,7 +130,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo while (isActive) { try { - channel.connect(coroutineContext + CoroutineName("Socket"), host, port) + channel.connect(host, port) break } catch (e: SocketException) { if (e is NoRouteToHostException || e.message?.contains("Network is unreachable") == true) { diff --git a/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt b/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt index 34cc719ff..f2370fd84 100644 --- a/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt +++ b/mirai-core/src/commonMain/kotlin/network/QQAndroidClient.kt @@ -24,8 +24,8 @@ import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY import net.mamoe.mirai.internal.network.protocol.packet.PacketLogger import net.mamoe.mirai.internal.network.protocol.packet.Tlv import net.mamoe.mirai.internal.utils.* -import net.mamoe.mirai.internal.utils.cryptor.ECDH -import net.mamoe.mirai.internal.utils.cryptor.TEA +import net.mamoe.mirai.internal.utils.crypto.ECDH +import net.mamoe.mirai.internal.utils.crypto.TEA import net.mamoe.mirai.network.LoginFailedException import net.mamoe.mirai.network.NoServerAvailableException import net.mamoe.mirai.utils.* diff --git a/mirai-core/src/commonMain/kotlin/network/highway/HighwayHelper.kt b/mirai-core/src/commonMain/kotlin/network/highway/HighwayHelper.kt index 709feeef1..ab4d38ea7 100644 --- a/mirai-core/src/commonMain/kotlin/network/highway/HighwayHelper.kt +++ b/mirai-core/src/commonMain/kotlin/network/highway/HighwayHelper.kt @@ -31,7 +31,6 @@ import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.withUse import net.mamoe.mirai.utils.internal.ReusableInput import net.mamoe.mirai.utils.verbose -import kotlin.coroutines.EmptyCoroutineContext import kotlin.math.roundToInt import kotlin.time.ExperimentalTime import kotlin.time.measureTime @@ -143,7 +142,7 @@ internal object HighwayHelper { val socket = PlatformSocket() while (client.bot.network.areYouOk() && client.bot.isActive) { try { - socket.connect(EmptyCoroutineContext, serverIp, serverPort) + socket.connect(serverIp, serverPort) break } catch (e: SocketException) { delay(3000) diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/EncryptMethod.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/EncryptMethod.kt index 8d4e2b1f4..9212bf445 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/EncryptMethod.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/EncryptMethod.kt @@ -14,8 +14,8 @@ import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.buildPacket import kotlinx.io.core.writeFully import net.mamoe.mirai.internal.network.QQAndroidClient -import net.mamoe.mirai.internal.utils.cryptor.ECDH -import net.mamoe.mirai.internal.utils.cryptor.ECDHKeyPair +import net.mamoe.mirai.internal.utils.crypto.ECDH +import net.mamoe.mirai.internal.utils.crypto.ECDHKeyPair import net.mamoe.mirai.internal.utils.io.encryptAndWrite import net.mamoe.mirai.internal.utils.io.writeShortLVByteArray diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt index 9c3efa7df..d6aa5c276 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/PacketFactory.kt @@ -26,8 +26,8 @@ import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc import net.mamoe.mirai.internal.network.protocol.packet.login.WtLogin import net.mamoe.mirai.internal.network.readUShortLVByteArray import net.mamoe.mirai.internal.utils.* -import net.mamoe.mirai.internal.utils.cryptor.TEA -import net.mamoe.mirai.internal.utils.cryptor.adjustToPublicKey +import net.mamoe.mirai.internal.utils.crypto.TEA +import net.mamoe.mirai.internal.utils.crypto.adjustToPublicKey import net.mamoe.mirai.internal.utils.io.readPacketExact import net.mamoe.mirai.internal.utils.io.readString import net.mamoe.mirai.internal.utils.io.useBytes diff --git a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/WtLogin.kt b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/WtLogin.kt index b7327ce93..8fb77cd5e 100644 --- a/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/WtLogin.kt +++ b/mirai-core/src/commonMain/kotlin/network/protocol/packet/login/WtLogin.kt @@ -16,7 +16,7 @@ import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.protocol.LoginType import net.mamoe.mirai.internal.network.protocol.packet.* import net.mamoe.mirai.internal.utils.* -import net.mamoe.mirai.internal.utils.cryptor.TEA +import net.mamoe.mirai.internal.utils.crypto.TEA import net.mamoe.mirai.internal.utils.guidFlag import net.mamoe.mirai.internal.utils.io.* import net.mamoe.mirai.utils.currentTimeSeconds diff --git a/mirai-core/src/commonMain/kotlin/utils/AtomicResizeCacheList.kt b/mirai-core/src/commonMain/kotlin/utils/AtomicResizeCacheList.kt deleted file mode 100644 index 45459d4eb..000000000 --- a/mirai-core/src/commonMain/kotlin/utils/AtomicResizeCacheList.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.internal.utils - -import kotlinx.atomicfu.AtomicLong -import kotlinx.atomicfu.atomic -import kotlinx.atomicfu.locks.reentrantLock -import kotlinx.atomicfu.locks.withLock -import net.mamoe.mirai.utils.currentTimeMillis - - -/** - * Dynamically sized cache list with retention period. - * No concurrency guaranteed on same elements. - */ -internal class AtomicResizeCacheList(private val retention: Long) { - private inner class Cache { - @Volatile - @JvmField - var element: E? = null - - val time: AtomicLong = atomic(0L) - } - - companion object { - const val initialCapacity: Int = 32 - } - - private val list: MutableList = ArrayList(initialCapacity) - private val lock = reentrantLock() - - /** - * Adds an element, also cleanup outdated caches, but no duplication is removed. - * No concurrency guaranteed on same [element]. - */ - private fun add(element: E) { - val currentTime = currentTimeMillis() - findAvailable@ while (true) { - for (cache in list) { - val instant = cache.time.value - when { - instant == 0L -> { - if (cache.time.compareAndSet(instant, currentTime + retention)) { - cache.element = element - return - } else continue@findAvailable - } - // outdated - instant < currentTime -> cache.time.compareAndSet(instant, 0) - } - } - // no more Cache instance available - lock.withLock { - list.add(Cache().apply { - this.element = element - this.time.value = currentTime + retention - }) - } - return - } - } - - /** - * No concurrency guaranteed on same [element] - */ - private fun removeDuplication(element: E): Boolean { - val duplicate = list.firstOrNull { it.time.value != 0L && it.element == element } ?: return false - duplicate.time.value = 0 - return true - } - - fun ensureNoDuplication(element: E): Boolean { - return if (removeDuplication(element)) { - false - } else { - add(element) - true - } - } -} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/utils/MiraiPlatformUtils.common.kt b/mirai-core/src/commonMain/kotlin/utils/MiraiPlatformUtils.kt similarity index 100% rename from mirai-core/src/commonMain/kotlin/utils/MiraiPlatformUtils.common.kt rename to mirai-core/src/commonMain/kotlin/utils/MiraiPlatformUtils.kt diff --git a/mirai-core/src/commonMain/kotlin/utils/PlatformDatagramChannel.kt b/mirai-core/src/commonMain/kotlin/utils/PlatformDatagramChannel.kt index da23812ba..2c4f9a8cc 100644 --- a/mirai-core/src/commonMain/kotlin/utils/PlatformDatagramChannel.kt +++ b/mirai-core/src/commonMain/kotlin/utils/PlatformDatagramChannel.kt @@ -9,26 +9,97 @@ package net.mamoe.mirai.internal.utils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.Closeable +import kotlinx.io.nio.readPacketAtMost +import kotlinx.io.nio.writePacket +import java.net.InetSocketAddress +import java.nio.channels.DatagramChannel +import java.nio.channels.ReadableByteChannel +import java.nio.channels.WritableByteChannel /** * 多平台适配的 DatagramChannel. */ -internal expect class PlatformDatagramChannel(serverHost: String, serverPort: Short) : Closeable { - /** - * @throws SendPacketInternalException - */ - suspend inline fun send(packet: ByteReadPacket): Boolean +internal class PlatformDatagramChannel(serverHost: String, serverPort: Short) : Closeable { + @PublishedApi + internal val channel: DatagramChannel = + DatagramChannel.open().connect(InetSocketAddress(serverHost, serverPort.toInt())) + val isOpen: Boolean get() = channel.isOpen + override fun close() = channel.close() - /** - * @throws ReadPacketInternalException - */ - suspend inline fun read(): ByteReadPacket + suspend inline fun send(packet: ByteReadPacket): Boolean = withContext(Dispatchers.IO) { + try { + (channel as WritableByteChannel).writePacket(packet) + } catch (e: Throwable) { + throw SendPacketInternalException(e) + } + } - val isOpen: Boolean + suspend inline fun read(): ByteReadPacket = withContext(Dispatchers.IO) { + try { + (channel as ReadableByteChannel).readPacketAtMost(Long.MAX_VALUE) + } catch (e: Throwable) { + throw ReadPacketInternalException(e) + } + } } +/* + +actual class PlatformDatagramChannel actual constructor(serverHost: String, serverPort: Short) : Closeable { + private val serverAddress: InetSocketAddress = InetSocketAddress(serverHost, serverPort.toInt()) + + @KtorExperimentalAPI + val socket = runBlocking { aSocket(ActorSelectorManager(Dispatchers.IO)).tcp() + .connect(remoteAddress = serverAddress) } + + @KtorExperimentalAPI + val readChannel = socket.openReadChannel() + + @KtorExperimentalAPI + val writeChannel = socket.openWriteChannel(true) + + @KtorExperimentalAPI + @Throws(ReadPacketInternalException::class) + actual suspend fun read(buffer: IoBuffer) = + try { + readChannel.readAvailable(buffer) + } catch (e: ClosedChannelException) { + throw e + } catch (e: Throwable) { + throw ReadPacketInternalException(e) + } + + + @KtorExperimentalAPI + @Throws(SendPacketInternalException::class) + actual suspend fun send(buffer: IoBuffer) = + buffer.readDirect { + try { + writeChannel.writeFully(it) + } catch (e: ClosedChannelException) { + throw e + } catch (e: Throwable) { + throw SendPacketInternalException(e) + } + } + + + @KtorExperimentalAPI + @Throws(IOException::class) + override fun close() { + socket.close() + } + + @KtorExperimentalAPI + actual val isOpen: Boolean + get() = socket.isClosed.not() +} + */ + /** * 在 [PlatformDatagramChannel.send] 或 [PlatformDatagramChannel.read] 时出现的错误. */ diff --git a/mirai-core/src/commonMain/kotlin/utils/PlatformSocket.kt b/mirai-core/src/commonMain/kotlin/utils/PlatformSocket.kt index 26f72229c..0e400197a 100644 --- a/mirai-core/src/commonMain/kotlin/utils/PlatformSocket.kt +++ b/mirai-core/src/commonMain/kotlin/utils/PlatformSocket.kt @@ -9,38 +9,95 @@ package net.mamoe.mirai.internal.utils +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.Closeable -import kotlinx.io.errors.IOException -import kotlin.coroutines.CoroutineContext +import kotlinx.io.streams.readPacketAtMost +import kotlinx.io.streams.writePacket +import java.io.BufferedInputStream +import java.io.BufferedOutputStream +import java.io.IOException +import java.net.NoRouteToHostException +import java.net.Socket +import java.net.UnknownHostException +import java.util.concurrent.Executors /** - * 多平台适配的 TCP Socket. + * TCP Socket. */ -internal expect class PlatformSocket() : Closeable { - @kotlin.Throws(SocketException::class) - suspend fun connect(coroutineContext: CoroutineContext, serverHost: String, serverPort: Int) +internal class PlatformSocket : Closeable { + private lateinit var socket: Socket + + val isOpen: Boolean + get() = + if (::socket.isInitialized) + socket.isConnected + else false + + override fun close() { + if (::socket.isInitialized) { + socket.close() + } + thread.shutdownNow() + } + + @PublishedApi + internal lateinit var writeChannel: BufferedOutputStream + + @PublishedApi + internal lateinit var readChannel: BufferedInputStream + + suspend fun send(packet: ByteArray, offset: Int, length: Int) { + @Suppress("BlockingMethodInNonBlockingContext") + withContext(Dispatchers.IO) { + writeChannel.write(packet, offset, length) + writeChannel.flush() + } + } /** * @throws SendPacketInternalException */ - suspend fun send(packet: ByteArray, offset: Int = 0, length: Int = packet.size - offset) + suspend fun send(packet: ByteReadPacket) { + @Suppress("BlockingMethodInNonBlockingContext") + withContext(Dispatchers.IO) { + try { + writeChannel.writePacket(packet) + writeChannel.flush() + } catch (e: IOException) { + throw SendPacketInternalException(e) + } + } + } - /** - * @throws SendPacketInternalException - */ - suspend fun send(packet: ByteReadPacket) + private val thread = Executors.newSingleThreadExecutor() /** * @throws ReadPacketInternalException */ - suspend fun read(): ByteReadPacket + suspend fun read(): ByteReadPacket = suspendCancellableCoroutine { cont -> + thread.submit { + kotlin.runCatching { + readChannel.readPacketAtMost(Long.MAX_VALUE) + }.let { + cont.resumeWith(it) + } + } + } - val isOpen: Boolean - - override fun close() + suspend fun connect(serverHost: String, serverPort: Int) { + @Suppress("BlockingMethodInNonBlockingContext") + withContext(Dispatchers.IO) { + socket = Socket(serverHost, serverPort) + readChannel = socket.getInputStream().buffered() + writeChannel = socket.getOutputStream().buffered() + } + } } -internal expect open class SocketException : IOException -internal expect class NoRouteToHostException : SocketException -internal expect class UnknownHostException : IOException \ No newline at end of file + +internal typealias SocketException = java.net.SocketException +internal typealias NoRouteToHostException = NoRouteToHostException +internal typealias UnknownHostException = UnknownHostException \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/utils/contentToString.kt b/mirai-core/src/commonMain/kotlin/utils/contentToString.kt index dfa0fa435..6c0c06ab2 100644 --- a/mirai-core/src/commonMain/kotlin/utils/contentToString.kt +++ b/mirai-core/src/commonMain/kotlin/utils/contentToString.kt @@ -135,7 +135,9 @@ internal fun Any?._miraiContentToString(prefix: String = ""): String = when (thi } } -internal expect fun KProperty1<*, *>.getValueAgainstPermission(receiver: Any): Any? +internal fun KProperty1<*, *>.getValueAgainstPermission(receiver: Any): Any? { + return this.javaField?.apply { isAccessible = true }?.get(receiver) +} private fun Any.canBeIgnored(): Boolean { return when (this) { diff --git a/mirai-core/src/commonMain/kotlin/utils/cryptor/ECDH.kt b/mirai-core/src/commonMain/kotlin/utils/crypto/ECDH.kt similarity index 96% rename from mirai-core/src/commonMain/kotlin/utils/cryptor/ECDH.kt rename to mirai-core/src/commonMain/kotlin/utils/crypto/ECDH.kt index 6d7fe372f..c5653451f 100644 --- a/mirai-core/src/commonMain/kotlin/utils/cryptor/ECDH.kt +++ b/mirai-core/src/commonMain/kotlin/utils/crypto/ECDH.kt @@ -7,13 +7,11 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -package net.mamoe.mirai.internal.utils.cryptor +package net.mamoe.mirai.internal.utils.crypto import net.mamoe.mirai.internal.utils.chunkedHexToBytes -internal expect interface ECDHPrivateKey { - fun getEncoded(): ByteArray -} +internal expect interface ECDHPrivateKey internal expect interface ECDHPublicKey { fun getEncoded(): ByteArray diff --git a/mirai-core/src/commonMain/kotlin/utils/cryptor/TEA.kt b/mirai-core/src/commonMain/kotlin/utils/crypto/TEA.kt similarity index 99% rename from mirai-core/src/commonMain/kotlin/utils/cryptor/TEA.kt rename to mirai-core/src/commonMain/kotlin/utils/crypto/TEA.kt index 86bacd815..adef059ca 100644 --- a/mirai-core/src/commonMain/kotlin/utils/cryptor/TEA.kt +++ b/mirai-core/src/commonMain/kotlin/utils/crypto/TEA.kt @@ -7,7 +7,7 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -package net.mamoe.mirai.internal.utils.cryptor +package net.mamoe.mirai.internal.utils.crypto import kotlinx.io.core.ByteReadPacket import kotlinx.io.pool.useInstance @@ -16,7 +16,6 @@ import net.mamoe.mirai.internal.utils.toByteArray import net.mamoe.mirai.internal.utils.toUHexString import kotlin.experimental.and import kotlin.experimental.xor -import kotlin.jvm.JvmStatic import kotlin.random.Random /** diff --git a/mirai-core/src/commonMain/kotlin/utils/io/output.kt b/mirai-core/src/commonMain/kotlin/utils/io/output.kt index ce46a8e6f..771ae7c10 100644 --- a/mirai-core/src/commonMain/kotlin/utils/io/output.kt +++ b/mirai-core/src/commonMain/kotlin/utils/io/output.kt @@ -15,9 +15,7 @@ package net.mamoe.mirai.internal.utils.io import kotlinx.io.core.* import net.mamoe.mirai.internal.utils.coerceAtMostOrFail -import net.mamoe.mirai.internal.utils.cryptor.TEA -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName +import net.mamoe.mirai.internal.utils.crypto.TEA internal fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLength: Int) { if (array.size <= maxLength) { diff --git a/mirai-core/src/jvmMain/kotlin/utils/PlatformSocket.kt b/mirai-core/src/jvmMain/kotlin/utils/PlatformSocket.kt deleted file mode 100644 index 610eb42d9..000000000 --- a/mirai-core/src/jvmMain/kotlin/utils/PlatformSocket.kt +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.internal.utils - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext -import kotlinx.io.core.ByteReadPacket -import kotlinx.io.core.Closeable -import kotlinx.io.errors.IOException -import kotlinx.io.streams.readPacketAtMost -import kotlinx.io.streams.writePacket -import java.io.BufferedInputStream -import java.io.BufferedOutputStream -import java.net.Socket -import java.net.SocketException -import java.util.concurrent.Executors -import kotlin.coroutines.CoroutineContext - -/** - * 多平台适配的 TCP Socket. - */ -internal actual class PlatformSocket : Closeable { - private lateinit var socket: Socket - - actual val isOpen: Boolean - get() = - if (::socket.isInitialized) - socket.isConnected - else false - - actual override fun close() { - if (::socket.isInitialized) { - socket.close() - } - thread.shutdownNow() - } - - @PublishedApi - internal lateinit var writeChannel: BufferedOutputStream - - @PublishedApi - internal lateinit var readChannel: BufferedInputStream - - actual suspend fun send(packet: ByteArray, offset: Int, length: Int) { - withContext(Dispatchers.IO) { - writeChannel.write(packet, offset, length) - writeChannel.flush() - } - } - - /** - * @throws SendPacketInternalException - */ - actual suspend fun send(packet: ByteReadPacket) { - withContext(Dispatchers.IO) { - try { - writeChannel.writePacket(packet) - writeChannel.flush() - } catch (e: IOException) { - throw SendPacketInternalException(e) - } - } - } - - private val thread = Executors.newSingleThreadExecutor() - - /** - * @throws ReadPacketInternalException - */ - actual suspend fun read(): ByteReadPacket = suspendCancellableCoroutine { cont -> - thread.submit { - kotlin.runCatching { - readChannel.readPacketAtMost(Long.MAX_VALUE) - }.let { - cont.resumeWith(it) - } - } - } - - actual suspend fun connect(coroutineContext: CoroutineContext, serverHost: String, serverPort: Int) { - withContext(Dispatchers.IO) { - socket = Socket(serverHost, serverPort) - readChannel = socket.getInputStream().buffered() - writeChannel = socket.getOutputStream().buffered() - } - } -} - -@Suppress("ACTUAL_WITHOUT_EXPECT") -internal actual typealias NoRouteToHostException = java.net.NoRouteToHostException - -@Suppress("ACTUAL_WITHOUT_EXPECT") -internal actual typealias SocketException = SocketException - -// ktor aSocket - -/* -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.internal.utils - -import io.ktor.network.selector.ActorSelectorManager -import io.ktor.network.sockets.* -import io.ktor.util.KtorExperimentalAPI -import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.ByteWriteChannel -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import kotlinx.io.core.ByteReadPacket -import kotlinx.io.core.Closeable -import kotlinx.io.core.ExperimentalIoApi -import kotlinx.io.core.buildPacket -import kotlinx.io.errors.IOException -import useBytes -import java.net.InetSocketAddress -import java.net.SocketException -import kotlin.coroutines.CoroutineContext - -/** - * 多平台适配的 TCP Socket. - */ -internal actual class PlatformSocket : Closeable { - private lateinit var socket: io.ktor.network.sockets.Socket - - actual val isOpen: Boolean - get() = - if (::socket.isInitialized) - !socket.isClosed - else false - - actual override fun close() { - if (::socket.isInitialized) { - socket.close() - } - } - - @PublishedApi - internal lateinit var writeChannel: ByteWriteChannel - - @PublishedApi - internal lateinit var readChannel: ByteReadChannel - - actual suspend fun send(packet: ByteArray, offset: Int, length: Int) { - withContext(Dispatchers.IO) { - writeChannel.writeFully(packet, offset, length) - } - } - - /** - * @throws SendPacketInternalException - */ - actual suspend fun send(packet: ByteReadPacket) { - withContext(Dispatchers.IO) { - try { - packet.useBytes { data: ByteArray, length: Int -> - writeChannel.writeFully(data, offset = 0, length = length) - } - } catch (e: IOException) { - throw SendPacketInternalException(e) - } - } - } - - /** - * @throws ReadPacketInternalException - */ - actual suspend fun read(): ByteReadPacket { - return withContext(Dispatchers.IO) { - try { - buildPacket { - readChannel.read { - writeFully(it) - } - } - } catch (e: IOException) { - throw ReadPacketInternalException(e) - } - } - } - - @OptIn(ExperimentalIoApi::class, KtorExperimentalAPI::class) - actual suspend fun connect(coroutineContext: CoroutineContext, serverHost: String, serverPort: Int) { - withContext(Dispatchers.IO) { - socket = aSocket(ActorSelectorManager(coroutineContext)).tcp().tcpNoDelay() - .connect(InetSocketAddress(serverHost, serverPort)) - readChannel = socket.openReadChannel() - writeChannel = socket.openWriteChannel(true) - } - } -} - -actual typealias NoRouteToHostException = java.net.NoRouteToHostException - -actual typealias SocketException = SocketException - */ -@Suppress("ACTUAL_WITHOUT_EXPECT") -internal actual typealias UnknownHostException = java.net.UnknownHostException \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/utils/PlatformSocketJvm.kt b/mirai-core/src/jvmMain/kotlin/utils/PlatformSocketJvm.kt deleted file mode 100644 index 07fba68c4..000000000 --- a/mirai-core/src/jvmMain/kotlin/utils/PlatformSocketJvm.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.internal.utils - -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import kotlinx.io.core.ByteReadPacket -import kotlinx.io.core.Closeable -import kotlinx.io.nio.readPacketAtMost -import kotlinx.io.nio.writePacket -import java.net.InetSocketAddress -import java.nio.channels.DatagramChannel -import java.nio.channels.ReadableByteChannel -import java.nio.channels.WritableByteChannel - - -/** - * 多平台适配的 DatagramChannel. - */ -internal actual class PlatformDatagramChannel actual constructor( - serverHost: String, - serverPort: Short -) : Closeable { - @PublishedApi - internal val channel: DatagramChannel = DatagramChannel.open().connect(InetSocketAddress(serverHost, serverPort.toInt())) - actual val isOpen: Boolean get() = channel.isOpen - override fun close() = channel.close() - - actual suspend inline fun send(packet: ByteReadPacket): Boolean = withContext(Dispatchers.IO) { - try { - (channel as WritableByteChannel).writePacket(packet) - } catch (e: Throwable) { - throw SendPacketInternalException(e) - } - } - - actual suspend inline fun read(): ByteReadPacket = withContext(Dispatchers.IO) { - try { - (channel as ReadableByteChannel).readPacketAtMost(Long.MAX_VALUE) - } catch (e: Throwable) { - throw ReadPacketInternalException(e) - } - } -} - -/* - -actual class PlatformDatagramChannel actual constructor(serverHost: String, serverPort: Short) : Closeable { - private val serverAddress: InetSocketAddress = InetSocketAddress(serverHost, serverPort.toInt()) - - @KtorExperimentalAPI - val socket = runBlocking { aSocket(ActorSelectorManager(Dispatchers.IO)).tcp() - .connect(remoteAddress = serverAddress) } - - @KtorExperimentalAPI - val readChannel = socket.openReadChannel() - - @KtorExperimentalAPI - val writeChannel = socket.openWriteChannel(true) - - @KtorExperimentalAPI - @Throws(ReadPacketInternalException::class) - actual suspend fun read(buffer: IoBuffer) = - try { - readChannel.readAvailable(buffer) - } catch (e: ClosedChannelException) { - throw e - } catch (e: Throwable) { - throw ReadPacketInternalException(e) - } - - - @KtorExperimentalAPI - @Throws(SendPacketInternalException::class) - actual suspend fun send(buffer: IoBuffer) = - buffer.readDirect { - try { - writeChannel.writeFully(it) - } catch (e: ClosedChannelException) { - throw e - } catch (e: Throwable) { - throw SendPacketInternalException(e) - } - } - - - @KtorExperimentalAPI - @Throws(IOException::class) - override fun close() { - socket.close() - } - - @KtorExperimentalAPI - actual val isOpen: Boolean - get() = socket.isClosed.not() -} - */ \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/utils/cryptor/ECDHJvm.kt b/mirai-core/src/jvmMain/kotlin/utils/crypto/ECDHJvmDesktop.kt similarity index 96% rename from mirai-core/src/jvmMain/kotlin/utils/cryptor/ECDHJvm.kt rename to mirai-core/src/jvmMain/kotlin/utils/crypto/ECDHJvmDesktop.kt index a64d76ac7..0203be8f7 100644 --- a/mirai-core/src/jvmMain/kotlin/utils/cryptor/ECDHJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/utils/crypto/ECDHJvmDesktop.kt @@ -7,7 +7,7 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -package net.mamoe.mirai.internal.utils.cryptor +package net.mamoe.mirai.internal.utils.crypto import net.mamoe.mirai.internal.utils.MiraiPlatformUtils import org.bouncycastle.jce.provider.BouncyCastleProvider @@ -31,9 +31,7 @@ internal actual class ECDHKeyPairImpl( override val initialShareKey: ByteArray by lazy { ECDH.calculateShareKey(privateKey, initialPublicKey) } } -@Suppress("FunctionName") -internal actual fun ECDH() = - ECDH(ECDH.generateKeyPair()) +internal actual fun ECDH() = ECDH(ECDH.generateKeyPair()) internal actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) { actual companion object { diff --git a/mirai-core/src/jvmMain/kotlin/utils/setVisible.kt b/mirai-core/src/jvmMain/kotlin/utils/setVisible.kt deleted file mode 100644 index d8437aaa0..000000000 --- a/mirai-core/src/jvmMain/kotlin/utils/setVisible.kt +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.internal.utils - -import kotlin.reflect.KProperty1 -import kotlin.reflect.jvm.javaField - -internal actual fun KProperty1<*, *>.getValueAgainstPermission(receiver: Any): Any? { - return this.javaField?.apply { isAccessible = true }?.get(receiver) -}