mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-23 06:10:30 +08:00
Pass compilation
This commit is contained in:
parent
e43120742c
commit
48850d7389
@ -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
|
@ -1,40 +1,41 @@
|
||||
package net.mamoe.mirai.qqandroid.network
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
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.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
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotNetworkHandler() {
|
||||
override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job])
|
||||
|
||||
private val channel: PlatformDatagramChannel = PlatformDatagramChannel("wtlogin.qq.com", 8000)
|
||||
|
||||
override suspend fun login() {
|
||||
launch { processReceive() }
|
||||
launch(CoroutineName("Incoming Packet Receiver")) { processReceive() }
|
||||
|
||||
val buffer = IoBuffer.Pool.borrow()
|
||||
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)
|
||||
LoginPacket(bot.client).sendAndExpect<LoginPacket.LoginPacketResponse>()
|
||||
println("Login sent")
|
||||
}
|
||||
|
||||
private suspend fun processReceive() {
|
||||
private suspend inline fun processReceive() {
|
||||
while (channel.isOpen) {
|
||||
val buffer = IoBuffer.Pool.borrow()
|
||||
|
||||
try {
|
||||
channel.read(buffer)// JVM: withContext(IO)
|
||||
val rawInput = try {
|
||||
channel.read()
|
||||
} catch (e: ClosedChannelException) {
|
||||
dispose()
|
||||
return
|
||||
@ -46,34 +47,49 @@ internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotN
|
||||
} catch (e: Throwable) {
|
||||
bot.logger.error("Caught unexpected exceptions", e)
|
||||
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("handleServerPacket")) {
|
||||
// `.use`: Ensure that the packet is consumed **totally**
|
||||
// so that all the buffers are released
|
||||
ByteArrayPool.useInstance {
|
||||
val length = buffer.readRemaining - 1
|
||||
buffer.readFully(it, 0, length)
|
||||
buffer.resetForWrite()
|
||||
buffer.writeFully(it, 0, length)
|
||||
}
|
||||
ByteReadPacket(buffer, IoBuffer.Pool).use { input ->
|
||||
launch(CoroutineName("Incoming Packet handler")) {
|
||||
try {
|
||||
input.debugPrint("Received")
|
||||
rawInput.debugPrint("Received")
|
||||
} catch (e: Exception) {
|
||||
bot.logger.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
rawInput.use {
|
||||
KnownPacketFactories.parseIncomingPacket(bot, rawInput) { packet: Packet, packetId: PacketId, sequenceId: Int ->
|
||||
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() {
|
||||
while (true) {
|
||||
|
@ -7,9 +7,9 @@ import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
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.cryptor.DecrypterByteArray
|
||||
import net.mamoe.mirai.utils.cryptor.ECDH
|
||||
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
|
||||
import net.mamoe.mirai.utils.cryptor.encryptBy
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
@ -21,7 +21,12 @@ import net.mamoe.mirai.utils.io.*
|
||||
internal class OutgoingPacket constructor(
|
||||
name: String?,
|
||||
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 name: String by lazy {
|
||||
@ -52,7 +57,7 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
|
||||
extraData: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: Short = PacketFactory.atomicNextSequenceId(),
|
||||
sequenceId: Int = PacketFactory.atomicNextSequenceId(),
|
||||
body: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket = OutgoingPacket(name, id, sequenceId, buildPacket {
|
||||
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)
|
||||
|
||||
/**
|
||||
@ -85,7 +85,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
|
||||
internal inline fun BytePacketBuilder.writeLoginSsoPacket(
|
||||
client: QQAndroidClient,
|
||||
subAppId: Long,
|
||||
commandId: CommandId,
|
||||
packetId: PacketId,
|
||||
extraData: ByteReadPacket = BRP_STUB,
|
||||
body: BytePacketBuilder.(ssoSequenceId: Int) -> Unit
|
||||
) {
|
||||
@ -102,21 +102,25 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
|
||||
writeInt((extraData.remaining + 4).toInt())
|
||||
writePacket(extraData)
|
||||
}
|
||||
writeInt(commandId.stringValue.length + 4)
|
||||
writeStringUtf8(commandId.stringValue)
|
||||
packetId.commandName.let {
|
||||
writeInt(it.length + 4)
|
||||
writeStringUtf8(it)
|
||||
}
|
||||
|
||||
writeInt(4 + 4)
|
||||
writeInt(45112203) // 02 B0 5B 8B
|
||||
|
||||
val imei = client.device.imei
|
||||
writeInt(imei.length + 4)
|
||||
writeStringUtf8(imei)
|
||||
client.device.imei.let {
|
||||
writeInt(it.length + 4)
|
||||
writeStringUtf8(it)
|
||||
}
|
||||
|
||||
writeInt(4)
|
||||
|
||||
val ksid = client.device.ksid
|
||||
writeShort((ksid.length + 2).toShort())
|
||||
writeStringUtf8(ksid)
|
||||
client.device.ksid.let {
|
||||
writeInt(it.length + 4)
|
||||
writeStringUtf8(it)
|
||||
}
|
||||
|
||||
writeInt(4)
|
||||
}
|
||||
@ -226,10 +230,10 @@ internal interface EncryptMethodECDH : EncryptMethod {
|
||||
override fun BytePacketBuilder.encryptAndWrite(body: ByteReadPacket) = ecdh.run {
|
||||
writeByte(1) // const
|
||||
writeByte(1) // const
|
||||
writeFully(privateKey)
|
||||
writeFully(keyPair.privateKey.getEncoded())
|
||||
writeShort(258) // const
|
||||
writeShortLVByteArray(publicKey)
|
||||
body.encryptBy(shareKey) { encrypted -> writeFully(encrypted) }
|
||||
writeShortLVByteArray(keyPair.publicKey.getEncoded().drop(23).toByteArray().also { check(it.size == 49) { "Bad publicKey generated. Expected size=49, got${it.size}" } })
|
||||
body.encryptBy(keyPair.shareKey) { encrypted -> writeFully(encrypted) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,8 +260,7 @@ internal interface EncryptMethodECDH : EncryptMethod {
|
||||
internal inline fun BytePacketBuilder.writeRequestPacket(
|
||||
client: QQAndroidClient,
|
||||
encryptMethod: EncryptMethod,
|
||||
commandId: CommandId,
|
||||
sequenceId: Short = PacketFactory.atomicNextSequenceId(),
|
||||
packetId: PacketId,
|
||||
bodyBlock: BytePacketBuilder.() -> Unit
|
||||
) {
|
||||
val body = encryptMethod.run {
|
||||
@ -268,8 +271,8 @@ internal inline fun BytePacketBuilder.writeRequestPacket(
|
||||
writeByte(0x02) // head
|
||||
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
|
||||
writeShort(client.protocolVersion)
|
||||
writeShort(sequenceId)
|
||||
writeShort(commandId.id.toShort())
|
||||
writeShort(1)
|
||||
writeShort(packetId.commandId.toShort())
|
||||
writeQQ(client.account.id)
|
||||
writeByte(3) // originally const
|
||||
writeByte(encryptMethod.id.toByte())
|
||||
|
@ -3,13 +3,21 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet
|
||||
import kotlinx.atomicfu.AtomicInt
|
||||
import kotlinx.atomicfu.atomic
|
||||
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.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.commandName
|
||||
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.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 {
|
||||
private val sequenceId: AtomicInt = atomic(1)
|
||||
|
||||
fun atomicNextSequenceId(): Short {
|
||||
fun atomicNextSequenceId(): Int {
|
||||
TODO("使用 SSO ")
|
||||
val id = sequenceId.getAndAdd(1)
|
||||
if (id > Short.MAX_VALUE.toInt() * 2) {
|
||||
sequenceId.value = 0
|
||||
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()
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
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.protocol.packet.*
|
||||
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) {
|
||||
init {
|
||||
this._id = PacketId(CommandId("wtlogin.login", 0x0810), 9)
|
||||
this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login", subCommandId = 9)
|
||||
}
|
||||
|
||||
operator fun invoke(
|
||||
@ -30,8 +30,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
|
||||
val appId = 16L
|
||||
val subAppId = 537062845L
|
||||
|
||||
writeLoginSsoPacket(client, subAppId, _id.commandId) { ssoSequenceId ->
|
||||
writeRequestPacket(client, EncryptMethodECDH135(client.ecdh), _id.commandId) {
|
||||
writeLoginSsoPacket(client, subAppId, id) { ssoSequenceId ->
|
||||
writeRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
|
||||
writeShort(9) // subCommand
|
||||
writeShort(LoginType.PASSWORD.value.toShort())
|
||||
|
||||
@ -163,30 +163,27 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
|
||||
|
||||
class LoginPacketResponse : Packet
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
override suspend fun ByteReadPacket.decode(id: PacketId, sequenceId: Short, handler: BotNetworkHandler): LoginPacketResponse {
|
||||
|
||||
TODO()
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): LoginPacketResponse {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Suppress("FunctionName")
|
||||
internal fun PacketId(commandId: CommandId, subCommandId: Int) = object : PacketId {
|
||||
override val commandId: CommandId
|
||||
get() = commandId
|
||||
override val subCommandId: Int
|
||||
get() = subCommandId
|
||||
internal fun PacketId(commandId: Int, commandName: String, subCommandId: Int) = object : PacketId {
|
||||
override val commandId: Int get() = commandId
|
||||
override val commandName: String get() = commandName
|
||||
override val subCommandId: Int get() = subCommandId
|
||||
}
|
||||
|
||||
internal interface PacketId {
|
||||
val commandId: CommandId // ushort actually
|
||||
val commandId: Int // ushort actually
|
||||
val commandName: String
|
||||
val subCommandId: Int // ushort actually
|
||||
}
|
||||
|
||||
internal object NullPacketId : PacketId {
|
||||
override val commandId: CommandId
|
||||
get() = error("uninitialized")
|
||||
override val subCommandId: Int
|
||||
get() = error("uninitialized")
|
||||
override val commandId: Int get() = error("uninitialized")
|
||||
override val commandName: String get() = error("uninitialized")
|
||||
override val subCommandId: Int get() = error("uninitialized")
|
||||
}
|
||||
|
@ -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
|
||||
}
|
@ -4,6 +4,7 @@ package net.mamoe.mirai.timpc.network.handler
|
||||
|
||||
import kotlinx.io.core.Closeable
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.PlatformDatagramChannel
|
||||
|
||||
/**
|
||||
@ -25,6 +26,7 @@ interface DataPacketSocketAdapter : Closeable {
|
||||
/**
|
||||
* UDP 通道
|
||||
*/
|
||||
@MiraiInternalAPI
|
||||
val channel: PlatformDatagramChannel
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ internal inline class PrivateKey(override val value: ByteArray) : DecrypterByteA
|
||||
}
|
||||
|
||||
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)
|
||||
(decrypted.remaining).let {
|
||||
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 {
|
||||
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"
|
||||
|
||||
|
@ -21,7 +21,7 @@ actual class ECDHKeyPair(
|
||||
@Suppress("FunctionName")
|
||||
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 fun generateKeyPair(): ECDHKeyPair {
|
||||
return ECDHKeyPair(KeyPairGenerator.getInstance("ECDH").genKeyPair())
|
||||
|
@ -19,6 +19,8 @@ expect class ECDHKeyPair {
|
||||
}
|
||||
|
||||
expect class ECDH(keyPair: ECDHKeyPair) {
|
||||
val keyPair: ECDHKeyPair
|
||||
|
||||
fun calculateShareKeyByPeerPublicKey(peerPublicKey: ECDHPublicKey): ByteArray
|
||||
|
||||
companion object {
|
||||
@ -47,5 +49,5 @@ fun ByteArray.adjustToPublicKey(): ECDHPublicKey {
|
||||
else (byteArray_04 + this)
|
||||
} else this
|
||||
|
||||
return ECDH.constructPublicKey(this)
|
||||
return ECDH.constructPublicKey(key)
|
||||
}
|
@ -21,7 +21,7 @@ actual class ECDHKeyPair(
|
||||
@Suppress("FunctionName")
|
||||
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 fun generateKeyPair(): ECDHKeyPair {
|
||||
return ECDHKeyPair(KeyPairGenerator.getInstance("ECDH").genKeyPair())
|
||||
|
Loading…
Reference in New Issue
Block a user