Pass compilation

This commit is contained in:
Him188 2020-01-06 21:29:57 +08:00
parent e43120742c
commit 48850d7389
11 changed files with 217 additions and 113 deletions

View File

@ -0,0 +1,10 @@
package net.mamoe.mirai.qqandroid.event
import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.Cancellable
import net.mamoe.mirai.event.Event
/**
* 接收到数据包
*/
class PacketReceivedEvent(val packet: Packet) : Event(), Cancellable

View File

@ -1,40 +1,41 @@
package net.mamoe.mirai.qqandroid.network package net.mamoe.mirai.qqandroid.network
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.io.core.* import kotlinx.io.core.use
import kotlinx.io.pool.useInstance import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.event.PacketReceivedEvent
import net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.ClosedChannelException
import net.mamoe.mirai.utils.io.PlatformDatagramChannel
import net.mamoe.mirai.utils.io.ReadPacketInternalException
import net.mamoe.mirai.utils.io.debugPrint
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@UseExperimental(MiraiInternalAPI::class)
internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotNetworkHandler() { internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotNetworkHandler() {
override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job]) override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job])
private val channel: PlatformDatagramChannel = PlatformDatagramChannel("wtlogin.qq.com", 8000) private val channel: PlatformDatagramChannel = PlatformDatagramChannel("wtlogin.qq.com", 8000)
override suspend fun login() { override suspend fun login() {
launch { processReceive() } launch(CoroutineName("Incoming Packet Receiver")) { processReceive() }
val buffer = IoBuffer.Pool.borrow() LoginPacket(bot.client).sendAndExpect<LoginPacket.LoginPacketResponse>()
buffer.writePacket(LoginPacket(bot.client).delegate)
val shouldBeSent = buffer.readRemaining
check(channel.send(buffer) == shouldBeSent) {
"Buffer is not entirely sent. " +
"Required sent length=$shouldBeSent, but after channel.send, " +
"buffer remains ${buffer.readBytes().toUHexString()}"
}
buffer.release(IoBuffer.Pool)
println("Login sent") println("Login sent")
} }
private suspend fun processReceive() { private suspend inline fun processReceive() {
while (channel.isOpen) { while (channel.isOpen) {
val buffer = IoBuffer.Pool.borrow() val rawInput = try {
channel.read()
try {
channel.read(buffer)// JVM: withContext(IO)
} catch (e: ClosedChannelException) { } catch (e: ClosedChannelException) {
dispose() dispose()
return return
@ -46,35 +47,50 @@ internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotN
} catch (e: Throwable) { } catch (e: Throwable) {
bot.logger.error("Caught unexpected exceptions", e) bot.logger.error("Caught unexpected exceptions", e)
continue continue
} finally {
if (!buffer.canRead() || buffer.readRemaining == 0) {//size==0
//bot.logger.debug("processReceive: Buffer cannot be read")
buffer.release(IoBuffer.Pool)
continue
}// sometimes exceptions are thrown without this `if` clause
} }
//buffer.resetForRead() launch(CoroutineName("Incoming Packet handler")) {
launch(CoroutineName("handleServerPacket")) { try {
// `.use`: Ensure that the packet is consumed **totally** rawInput.debugPrint("Received")
// so that all the buffers are released } catch (e: Exception) {
ByteArrayPool.useInstance { bot.logger.error(e)
val length = buffer.readRemaining - 1
buffer.readFully(it, 0, length)
buffer.resetForWrite()
buffer.writeFully(it, 0, length)
} }
ByteReadPacket(buffer, IoBuffer.Pool).use { input -> }
try {
input.debugPrint("Received") rawInput.use {
} catch (e: Exception) { KnownPacketFactories.parseIncomingPacket(bot, rawInput) { packet: Packet, packetId: PacketId, sequenceId: Int ->
bot.logger.error(e) if (PacketReceivedEvent(packet).broadcast().cancelled) {
return
}
packetListeners.forEach { listener ->
if (listener.filter(packetId, sequenceId) && packetListeners.remove(listener)) {
listener.complete(packet)
}
} }
} }
} }
} }
} }
suspend fun <E : Packet> OutgoingPacket.sendAndExpect(): E {
val handler = PacketListener(packetId = packetId, sequenceId = sequenceId)
packetListeners.addLast(handler)
check(channel.send(delegate)) { packetListeners.remove(handler); "Cannot send packet" }
@Suppress("UNCHECKED_CAST")
return handler.await() as E
}
@PublishedApi
internal val packetListeners = LockFreeLinkedList<PacketListener>()
@PublishedApi
internal inner class PacketListener(
val packetId: PacketId,
val sequenceId: Int
) : CompletableDeferred<Packet> by CompletableDeferred(supervisor) {
fun filter(packetId: PacketId, sequenceId: Int) = this.packetId == packetId && this.sequenceId == sequenceId
}
override suspend fun awaitDisconnection() { override suspend fun awaitDisconnection() {
while (true) { while (true) {
delay(100) delay(100)

View File

@ -7,9 +7,9 @@ import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.qqandroid.utils.ECDH
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import net.mamoe.mirai.utils.cryptor.ECDH
import net.mamoe.mirai.utils.cryptor.encryptAndWrite import net.mamoe.mirai.utils.cryptor.encryptAndWrite
import net.mamoe.mirai.utils.cryptor.encryptBy import net.mamoe.mirai.utils.cryptor.encryptBy
import net.mamoe.mirai.utils.io.* import net.mamoe.mirai.utils.io.*
@ -21,7 +21,12 @@ import net.mamoe.mirai.utils.io.*
internal class OutgoingPacket constructor( internal class OutgoingPacket constructor(
name: String?, name: String?,
val packetId: PacketId, val packetId: PacketId,
val sequenceId: Short, val sequenceId: Int,
// TODO: 2020/1/6 这个 sequenceId 设计有问题.
// 02 03 包里面的那个应该并不是 sequenceId.
// 它应该是固定的 0x001.
// 应该在这里填入 SSO 的 sequenceId.
// 同时考虑修改名称. 这可能不应该叫做 SSO. 它在全程都有
val delegate: ByteReadPacket val delegate: ByteReadPacket
) { ) {
val name: String by lazy { val name: String by lazy {
@ -52,7 +57,7 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
extraData: ByteArray = EMPTY_BYTE_ARRAY, extraData: ByteArray = EMPTY_BYTE_ARRAY,
name: String? = null, name: String? = null,
id: PacketId = this.id, id: PacketId = this.id,
sequenceId: Short = PacketFactory.atomicNextSequenceId(), sequenceId: Int = PacketFactory.atomicNextSequenceId(),
body: BytePacketBuilder.() -> Unit body: BytePacketBuilder.() -> Unit
): OutgoingPacket = OutgoingPacket(name, id, sequenceId, buildPacket { ): OutgoingPacket = OutgoingPacket(name, id, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
@ -69,11 +74,6 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
} }
}) })
internal class CommandId(val stringValue: String, val id: Int) {
override fun toString(): String = stringValue
}
private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY) private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
/** /**
@ -85,7 +85,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
internal inline fun BytePacketBuilder.writeLoginSsoPacket( internal inline fun BytePacketBuilder.writeLoginSsoPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, subAppId: Long,
commandId: CommandId, packetId: PacketId,
extraData: ByteReadPacket = BRP_STUB, extraData: ByteReadPacket = BRP_STUB,
body: BytePacketBuilder.(ssoSequenceId: Int) -> Unit body: BytePacketBuilder.(ssoSequenceId: Int) -> Unit
) { ) {
@ -102,21 +102,25 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
writeInt((extraData.remaining + 4).toInt()) writeInt((extraData.remaining + 4).toInt())
writePacket(extraData) writePacket(extraData)
} }
writeInt(commandId.stringValue.length + 4) packetId.commandName.let {
writeStringUtf8(commandId.stringValue) writeInt(it.length + 4)
writeStringUtf8(it)
}
writeInt(4 + 4) writeInt(4 + 4)
writeInt(45112203) // 02 B0 5B 8B writeInt(45112203) // 02 B0 5B 8B
val imei = client.device.imei client.device.imei.let {
writeInt(imei.length + 4) writeInt(it.length + 4)
writeStringUtf8(imei) writeStringUtf8(it)
}
writeInt(4) writeInt(4)
val ksid = client.device.ksid client.device.ksid.let {
writeShort((ksid.length + 2).toShort()) writeInt(it.length + 4)
writeStringUtf8(ksid) writeStringUtf8(it)
}
writeInt(4) writeInt(4)
} }
@ -226,10 +230,10 @@ internal interface EncryptMethodECDH : EncryptMethod {
override fun BytePacketBuilder.encryptAndWrite(body: ByteReadPacket) = ecdh.run { override fun BytePacketBuilder.encryptAndWrite(body: ByteReadPacket) = ecdh.run {
writeByte(1) // const writeByte(1) // const
writeByte(1) // const writeByte(1) // const
writeFully(privateKey) writeFully(keyPair.privateKey.getEncoded())
writeShort(258) // const writeShort(258) // const
writeShortLVByteArray(publicKey) writeShortLVByteArray(keyPair.publicKey.getEncoded().drop(23).toByteArray().also { check(it.size == 49) { "Bad publicKey generated. Expected size=49, got${it.size}" } })
body.encryptBy(shareKey) { encrypted -> writeFully(encrypted) } body.encryptBy(keyPair.shareKey) { encrypted -> writeFully(encrypted) }
} }
} }
@ -256,8 +260,7 @@ internal interface EncryptMethodECDH : EncryptMethod {
internal inline fun BytePacketBuilder.writeRequestPacket( internal inline fun BytePacketBuilder.writeRequestPacket(
client: QQAndroidClient, client: QQAndroidClient,
encryptMethod: EncryptMethod, encryptMethod: EncryptMethod,
commandId: CommandId, packetId: PacketId,
sequenceId: Short = PacketFactory.atomicNextSequenceId(),
bodyBlock: BytePacketBuilder.() -> Unit bodyBlock: BytePacketBuilder.() -> Unit
) { ) {
val body = encryptMethod.run { val body = encryptMethod.run {
@ -268,8 +271,8 @@ internal inline fun BytePacketBuilder.writeRequestPacket(
writeByte(0x02) // head writeByte(0x02) // head
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
writeShort(client.protocolVersion) writeShort(client.protocolVersion)
writeShort(sequenceId) writeShort(1)
writeShort(commandId.id.toShort()) writeShort(packetId.commandId.toShort())
writeQQ(client.account.id) writeQQ(client.account.id)
writeByte(3) // originally const writeByte(3) // originally const
writeByte(encryptMethod.id.toByte()) writeByte(encryptMethod.id.toByte())

View File

@ -3,13 +3,21 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet
import kotlinx.atomicfu.AtomicInt import kotlinx.atomicfu.AtomicInt
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.Closeable
import kotlinx.io.core.discardExact
import kotlinx.io.core.readBytes
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId.commandName
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.utils.LockFreeLinkedList
import net.mamoe.mirai.utils.cryptor.Decrypter import net.mamoe.mirai.utils.cryptor.Decrypter
import net.mamoe.mirai.utils.cryptor.DecrypterType import net.mamoe.mirai.utils.cryptor.DecrypterType
import net.mamoe.mirai.utils.cryptor.adjustToPublicKey
import net.mamoe.mirai.utils.cryptor.decryptBy
import net.mamoe.mirai.utils.io.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
/** /**
* 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包 * 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包
@ -32,21 +40,109 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
/** /**
* **解码**服务器的回复数据包 * **解码**服务器的回复数据包
*/ */
abstract suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: Short, handler: BotNetworkHandler): TPacket abstract suspend fun ByteReadPacket.decode(bot: QQAndroidBot): TPacket
companion object { companion object {
private val sequenceId: AtomicInt = atomic(1) private val sequenceId: AtomicInt = atomic(1)
fun atomicNextSequenceId(): Short { fun atomicNextSequenceId(): Int {
TODO("使用 SSO ")
val id = sequenceId.getAndAdd(1) val id = sequenceId.getAndAdd(1)
if (id > Short.MAX_VALUE.toInt() * 2) { if (id > Short.MAX_VALUE.toInt() * 2) {
sequenceId.value = 0 sequenceId.value = 0
return atomicNextSequenceId() return atomicNextSequenceId()
} }
return id.toShort() // return id.toShort()
} }
} }
} }
internal class KnownPacketFactories : LockFreeLinkedList<PacketFactory<*, *>>() { private val DECRYPTER_16_ZERO = ByteArray(16)
internal typealias PacketConsumer = (packet: Packet, packetId: PacketId, ssoSequenceId: Int) -> Unit
internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListOf() {
fun findPacketFactory(commandName: String): PacketFactory<*, *> = this.first { it.id.commandName == commandName }
fun findPacketFactory(commandId: Int): PacketFactory<*, *> = this.first { it.id.commandName == commandName }
suspend inline fun parseIncomingPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
rawInput.debugPrintIfFail("Incoming packet") {
require(rawInput.remaining < Int.MAX_VALUE) { "rawInput is too long" }
val expectedLength = readInt() - 4
check(rawInput.remaining.toInt() == expectedLength) { "Invalid packet length. Expected $expectedLength, got ${rawInput.remaining} Probably packets merged? " }
// login
when (val flag1 = readInt()) {
0x0A -> when (val flag2 = readByte().toInt()) {
0x02 -> {
val flag3 = readByte().toInt()
check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" }
discardExact(readInt() - 4) // uinAccount
parseLoginSsoPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
}
else -> error("Illegal flag2. Expected 0x02, got $flag2")
}
else -> error("Illegal flag1. Expected 0x0A or 0x0B, got $flag1")
}
}
@UseExperimental(ExperimentalUnsignedTypes::class)
private suspend inline fun parseLoginSsoPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
rawInput.debugPrintIfFail("Login sso packet") {
val commandName: String
val ssoSequenceId: Int
readIoBuffer(readInt() - 4).withUse {
ssoSequenceId = readInt()
check(readInt() == 0)
val loginExtraData = readIoBuffer(readInt() - 4)
commandName = readString(readInt() - 4)
val unknown = readBytes(readInt() - 4)
if (unknown.toInt() != 0x02B05B8B) DebugLogger.debug("got new unknown: $unknown")
check(readInt() == 0)
}
val packetFactory = findPacketFactory(commandName)
val qq: Long
val subCommandId: Int
readIoBuffer(readInt() - 4).withUse {
check(readByte().toInt() == 2)
discardExact(2) // 27 + 2 + body.size
discardExact(2) // const, =8001
readShort() // commandId
readShort() // innerSequenceId
qq = readInt().toLong()
discardExact(1) // const = 0
val packet = when (val encryptionMethod = readByte().toInt()) {
4 -> { // peer public key, ECDH
packetFactory.run {
bot.client.ecdh.calculateShareKeyByPeerPublicKey(readUShortLVByteArray().adjustToPublicKey()).read {
decode(bot)
}
}
}
else -> error("Illegal encryption method. expected 4, got $encryptionMethod")
}
consumer(packet, packetFactory.id, ssoSequenceId)
}
}
}
@UseExperimental(ExperimentalContracts::class)
internal inline fun <I : Closeable, R> I.withUse(block: I.() -> R): R {
contract {
callsInPlace(block, kotlin.contracts.InvocationKind.EXACTLY_ONCE)
}
return try {
block(this)
} finally {
close()
}
} }

View File

@ -5,7 +5,7 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket import kotlinx.io.core.buildPacket
import kotlinx.io.core.readBytes import kotlinx.io.core.readBytes
import net.mamoe.mirai.data.Packet import net.mamoe.mirai.data.Packet
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.* import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.qqandroid.utils.GuidSource import net.mamoe.mirai.qqandroid.utils.GuidSource
@ -21,7 +21,7 @@ class LoginPacketDecrypter(override val value: ByteArray) : DecrypterByteArray {
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, LoginPacketDecrypter>(LoginPacketDecrypter) { internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, LoginPacketDecrypter>(LoginPacketDecrypter) {
init { init {
this._id = PacketId(CommandId("wtlogin.login", 0x0810), 9) this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login", subCommandId = 9)
} }
operator fun invoke( operator fun invoke(
@ -30,8 +30,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
val appId = 16L val appId = 16L
val subAppId = 537062845L val subAppId = 537062845L
writeLoginSsoPacket(client, subAppId, _id.commandId) { ssoSequenceId -> writeLoginSsoPacket(client, subAppId, id) { ssoSequenceId ->
writeRequestPacket(client, EncryptMethodECDH135(client.ecdh), _id.commandId) { writeRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
writeShort(9) // subCommand writeShort(9) // subCommand
writeShort(LoginType.PASSWORD.value.toShort()) writeShort(LoginType.PASSWORD.value.toShort())
@ -163,30 +163,27 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
class LoginPacketResponse : Packet class LoginPacketResponse : Packet
@ExperimentalUnsignedTypes override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): LoginPacketResponse {
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: Short, handler: BotNetworkHandler): LoginPacketResponse { TODO("not implemented")
TODO()
} }
} }
@Suppress("FunctionName") @Suppress("FunctionName")
internal fun PacketId(commandId: CommandId, subCommandId: Int) = object : PacketId { internal fun PacketId(commandId: Int, commandName: String, subCommandId: Int) = object : PacketId {
override val commandId: CommandId override val commandId: Int get() = commandId
get() = commandId override val commandName: String get() = commandName
override val subCommandId: Int override val subCommandId: Int get() = subCommandId
get() = subCommandId
} }
internal interface PacketId { internal interface PacketId {
val commandId: CommandId // ushort actually val commandId: Int // ushort actually
val commandName: String
val subCommandId: Int // ushort actually val subCommandId: Int // ushort actually
} }
internal object NullPacketId : PacketId { internal object NullPacketId : PacketId {
override val commandId: CommandId override val commandId: Int get() = error("uninitialized")
get() = error("uninitialized") override val commandName: String get() = error("uninitialized")
override val subCommandId: Int override val subCommandId: Int get() = error("uninitialized")
get() = error("uninitialized")
} }

View File

@ -1,22 +0,0 @@
package net.mamoe.mirai.qqandroid.utils
/**
* From QQAndroid 8.2.0
* `oicq.wlogin_sdk.tools.EcdhCrypt`
*
* Constant to avoid calculations
*/
interface ECDH {
/*
object Default : ECDH {
override val publicKey: ByteArray = "020b03cf3d99541f29ffec281bebbd4ea211292ac1f53d7128".chunkedHexToBytes()
override val shareKey: ByteArray = "4da0f614fc9f29c2054c77048a6566d7".chunkedHexToBytes()
override val privateKey: ByteArray = ByteArray(16)
}*/
val publicKey: ByteArray
val shareKey: ByteArray
val privateKey: ByteArray
}

View File

@ -4,6 +4,7 @@ package net.mamoe.mirai.timpc.network.handler
import kotlinx.io.core.Closeable import kotlinx.io.core.Closeable
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.io.PlatformDatagramChannel import net.mamoe.mirai.utils.io.PlatformDatagramChannel
/** /**
@ -25,6 +26,7 @@ interface DataPacketSocketAdapter : Closeable {
/** /**
* UDP 通道 * UDP 通道
*/ */
@MiraiInternalAPI
val channel: PlatformDatagramChannel val channel: PlatformDatagramChannel
/** /**

View File

@ -26,7 +26,7 @@ internal inline class PrivateKey(override val value: ByteArray) : DecrypterByteA
} }
internal inline class SubmitPasswordResponseDecrypter(private val privateKey: PrivateKey) : Decrypter { internal inline class SubmitPasswordResponseDecrypter(private val privateKey: PrivateKey) : Decrypter {
override fun decrypt(input: ByteReadPacket): ByteReadPacket { override fun decrypt(input: ByteReadPacket, offset: Int, length: Int): ByteReadPacket {
var decrypted = ShareKey.decrypt(input) var decrypted = ShareKey.decrypt(input)
(decrypted.remaining).let { (decrypted.remaining).let {
if (it.toInt() % 8 == 0 && it >= 16) { if (it.toInt() % 8 == 0 && it >= 16) {
@ -263,7 +263,7 @@ internal object SubmitPasswordPacket : PacketFactory<SubmitPasswordPacket.LoginR
} }
internal inline class SessionResponseDecryptionKey(private val delegate: IoBuffer) : Decrypter { internal inline class SessionResponseDecryptionKey(private val delegate: IoBuffer) : Decrypter {
override fun decrypt(input: ByteReadPacket): ByteReadPacket = input.decryptBy(delegate) override fun decrypt(input: ByteReadPacket, offset: Int, length: Int): ByteReadPacket = input.decryptBy(delegate)
override fun toString(): String = "SessionResponseDecryptionKey" override fun toString(): String = "SessionResponseDecryptionKey"

View File

@ -21,7 +21,7 @@ actual class ECDHKeyPair(
@Suppress("FunctionName") @Suppress("FunctionName")
actual fun ECDH() = ECDH(ECDH.generateKeyPair()) actual fun ECDH() = ECDH(ECDH.generateKeyPair())
actual class ECDH actual constructor(val keyPair: ECDHKeyPair) { actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
actual companion object { actual companion object {
actual fun generateKeyPair(): ECDHKeyPair { actual fun generateKeyPair(): ECDHKeyPair {
return ECDHKeyPair(KeyPairGenerator.getInstance("ECDH").genKeyPair()) return ECDHKeyPair(KeyPairGenerator.getInstance("ECDH").genKeyPair())

View File

@ -19,6 +19,8 @@ expect class ECDHKeyPair {
} }
expect class ECDH(keyPair: ECDHKeyPair) { expect class ECDH(keyPair: ECDHKeyPair) {
val keyPair: ECDHKeyPair
fun calculateShareKeyByPeerPublicKey(peerPublicKey: ECDHPublicKey): ByteArray fun calculateShareKeyByPeerPublicKey(peerPublicKey: ECDHPublicKey): ByteArray
companion object { companion object {
@ -47,5 +49,5 @@ fun ByteArray.adjustToPublicKey(): ECDHPublicKey {
else (byteArray_04 + this) else (byteArray_04 + this)
} else this } else this
return ECDH.constructPublicKey(this) return ECDH.constructPublicKey(key)
} }

View File

@ -21,7 +21,7 @@ actual class ECDHKeyPair(
@Suppress("FunctionName") @Suppress("FunctionName")
actual fun ECDH() = ECDH(ECDH.generateKeyPair()) actual fun ECDH() = ECDH(ECDH.generateKeyPair())
actual class ECDH actual constructor(val keyPair: ECDHKeyPair) { actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
actual companion object { actual companion object {
actual fun generateKeyPair(): ECDHKeyPair { actual fun generateKeyPair(): ECDHKeyPair {
return ECDHKeyPair(KeyPairGenerator.getInstance("ECDH").genKeyPair()) return ECDHKeyPair(KeyPairGenerator.getInstance("ECDH").genKeyPair())