Commit 181ab6e3 authored by Him188's avatar Him188

Improve performance

parent 2aaff44c
......@@ -32,9 +32,9 @@ internal actual class ECDHKeyPairImpl(
}
@Suppress("FunctionName")
actual fun ECDH() = ECDH(ECDH.generateKeyPair())
internal actual fun ECDH() = ECDH(ECDH.generateKeyPair())
actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
internal actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
actual companion object {
@Suppress("ObjectPropertyName")
private var _isECDHAvailable: Boolean = false // because `runCatching` has no contract.
......
......@@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.qqandroid
import io.ktor.client.HttpClient
......@@ -34,7 +36,6 @@ import net.mamoe.mirai.qqandroid.contact.MemberInfoImpl
import net.mamoe.mirai.qqandroid.contact.QQImpl
import net.mamoe.mirai.qqandroid.contact.checkIsGroupImpl
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.message.MessageSourceFromSendFriend
import net.mamoe.mirai.qqandroid.message.OnlineFriendImageImpl
import net.mamoe.mirai.qqandroid.message.OnlineGroupImageImpl
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
......@@ -373,29 +374,17 @@ internal abstract class QQAndroidBotBase constructor(
check(chain.toString().length <= 4500 && chain.count { it is Image } <= 50) { "message is too large. Allow up to 4500 chars or 50 images" }
val group = getGroup(groupCode)
val source = MessageSourceFromSendFriend(
messageRandom = Random.nextInt().absoluteValue,
senderId = client.uin,
toUin = Group.calculateGroupUinByGroupCode(groupCode),
time = currentTimeSeconds,
groupId = groupCode,
originalMessage = chain,
sequenceId = client.atomicNextMessageSequenceId()
// sourceMessage = message
)
// TODO: 2020/3/26 util 方法来添加单例元素
val toSend = buildMessageChain(chain.size) {
source.originalMessage.forEach {
if (it !is MessageSource) {
add(it)
}
}
add(source)
}
val time = currentTimeSeconds
network.run {
val data = toSend.calculateValidationDataForGroup(group)
val data = chain.calculateValidationDataForGroup(
sequenceId = client.atomicNextMessageSequenceId(),
time = time.toInt(),
random = Random.nextInt().absoluteValue.toULong().toLong(),
group
)
val response =
MultiMsg.ApplyUp.createForGroupLongMessage(
......@@ -443,7 +432,7 @@ internal abstract class QQAndroidBotBase constructor(
group.sendMessage(
RichMessage.longMessage(
brief = toSend.joinToString(limit = 30) {
brief = chain.joinToString(limit = 30) {
when (it) {
is PlainText -> it.stringValue
is At -> it.toString()
......@@ -451,7 +440,7 @@ internal abstract class QQAndroidBotBase constructor(
}
},
resId = resId,
timeSeconds = source.time
timeSeconds = time
)
)
}
......
......@@ -27,14 +27,17 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.Heartbeat
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.WtLogin
import net.mamoe.mirai.qqandroid.network.readUShortLVByteArray
import net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import net.mamoe.mirai.qqandroid.utils.cryptor.adjustToPublicKey
import net.mamoe.mirai.qqandroid.utils.io.readPacketExact
import net.mamoe.mirai.qqandroid.utils.io.readString
import net.mamoe.mirai.qqandroid.utils.io.useBytes
import net.mamoe.mirai.qqandroid.utils.io.withUse
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.qqandroid.utils.cryptor.TEA
import net.mamoe.mirai.qqandroid.utils.cryptor.adjustToPublicKey
import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.io.ByteArrayPool
import net.mamoe.mirai.utils.io.toInt
import net.mamoe.mirai.utils.io.toReadPacket
import net.mamoe.mirai.utils.io.toUHexString
import kotlin.jvm.JvmName
......@@ -171,9 +174,6 @@ internal object KnownPacketFactories {
?: IncomingFactories.firstOrNull { it.receivingCommandName == commandName }
}
/**
* full packet without length
*/
// do not inline. Exceptions thrown will not be reported correctly
@OptIn(MiraiInternalAPI::class)
@Suppress("UNCHECKED_CAST")
......@@ -183,22 +183,12 @@ internal object KnownPacketFactories {
val flag1 = readInt()
PacketLogger.verbose { "开始处理一个包" }
PacketLogger.verbose { "flag1(0A/0B) = ${flag1.toUByte().toUHexString()}" }
val flag2 = readByte().toInt()
PacketLogger.verbose {
"包类型(flag2) = $flag2. (可能是 ${when (flag2) {
2 -> "OicqRequest"
1 -> "Uni/ProtoBuf"
0 -> "Heartbeat"
else -> "未知"
}})"
}
val flag3 = readByte().toInt()
check(flag3 == 0) {
"Illegal flag3. Expected 0, whereas got $flag3. flag1=$flag1, flag2=$flag2. Remaining=${this.readBytes()
.toUHexString()}"
"Illegal flag3. Expected 0, whereas got $flag3. flag1=$flag1, flag2=$flag2. " +
"Remaining=${this.readBytes().toUHexString()}"
}
readString(readInt() - 4)// uinAccount
......@@ -209,14 +199,11 @@ internal object KnownPacketFactories {
kotlin.runCatching {
when (flag2) {
2 -> TEA.decrypt(data, DECRYPTER_16_ZERO, size)
.also { PacketLogger.verbose { "成功使用 16 zero 解密" } }
1 -> TEA.decrypt(data, bot.client.wLoginSigInfo.d2Key, size)
.also { PacketLogger.verbose { "成功使用 d2Key 解密" } }
0 -> data
else -> error("")
}
}.getOrElse {
PacketLogger.verbose { "失败, 尝试其他各种key" }
bot.client.tryDecryptOrNull(data, size) { it }
}?.toReadPacket()?.let { decryptedData ->
when (flag1) {
......@@ -236,7 +223,7 @@ internal object KnownPacketFactories {
} else {
handleIncomingPacket(it, bot, flag2, consumer)
}
} ?: inline {
} ?: kotlin.run {
PacketLogger.error { "任何key都无法解密: ${data.take(size).toUHexString()}" }
return
}
......@@ -295,8 +282,6 @@ internal object KnownPacketFactories {
}
}
private inline fun <R> inline(block: () -> R): R = block()
class IncomingPacket<T : Packet?>(
val packetFactory: PacketFactory<T>?,
val sequenceId: Int,
......@@ -358,9 +343,7 @@ internal object KnownPacketFactories {
}
}
}
8 -> {
input
}
8 -> input
else -> error("unknown dataCompressed flag: $dataCompressed")
}
......
......@@ -21,7 +21,7 @@ expect interface ECDHPublicKey {
internal expect class ECDHKeyPairImpl : ECDHKeyPair
interface ECDHKeyPair {
internal interface ECDHKeyPair {
val privateKey: ECDHPrivateKey
val publicKey: ECDHPublicKey
......@@ -43,7 +43,7 @@ interface ECDHKeyPair {
/**
* 椭圆曲线密码, ECDH 加密
*/
expect class ECDH(keyPair: ECDHKeyPair) {
internal expect class ECDH(keyPair: ECDHKeyPair) {
val keyPair: ECDHKeyPair
/**
......@@ -74,9 +74,9 @@ expect class ECDH(keyPair: ECDHKeyPair) {
}
@Suppress("FunctionName")
expect fun ECDH(): ECDH
internal expect fun ECDH(): ECDH
val initialPublicKey
internal val initialPublicKey
get() = ECDH.constructPublicKey("3046301006072A8648CE3D020106052B8104001F03320004928D8850673088B343264E0C6BACB8496D697799F37211DEB25BB73906CB089FEA9639B4E0260498B51A992D50813DA8".chunkedHexToBytes())
private val commonHeadFor02 = "302E301006072A8648CE3D020106052B8104001F031A00".chunkedHexToBytes()
private val commonHeadForNot02 = "3046301006072A8648CE3D020106052B8104001F033200".chunkedHexToBytes()
......@@ -86,7 +86,7 @@ private val byteArray_04 = byteArrayOf(0x04)
private val head1 = "302E301006072A8648CE3D020106052B8104001F031A00".chunkedHexToBytes()
private val head2 = "3046301006072A8648CE3D020106052B8104001F03320004".chunkedHexToBytes()
fun ByteArray.adjustToPublicKey(): ECDHPublicKey {
internal fun ByteArray.adjustToPublicKey(): ECDHPublicKey {
val head = if (this.size < 30) head1 else head2
return ECDH.constructPublicKey(head + this)
......
......@@ -23,7 +23,7 @@ import kotlin.random.Random
/**
* 解密错误
*/
class DecryptionFailedException : Exception {
internal class DecryptionFailedException : Exception {
constructor() : super()
constructor(message: String?) : super(message)
}
......@@ -34,7 +34,7 @@ class DecryptionFailedException : Exception {
* **注意**: 此为 Mirai 内部 API. 它可能会在任何时刻被改变.
*/
@MiraiInternalAPI
object TEA {
internal object TEA {
// TODO: 2020/2/28 使用 stream 式输入以避免缓存
/**
......
......@@ -20,7 +20,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLength: Int) {
internal fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLength: Int) {
if (array.size <= maxLength) {
writeShort(array.size.toShort())
writeFully(array)
......@@ -32,13 +32,13 @@ fun BytePacketBuilder.writeShortLVByteArrayLimitedLength(array: ByteArray, maxLe
}
}
inline fun BytePacketBuilder.writeShortLVByteArray(byteArray: ByteArray): Int {
internal inline fun BytePacketBuilder.writeShortLVByteArray(byteArray: ByteArray): Int {
this.writeShort(byteArray.size.toShort())
this.writeFully(byteArray)
return byteArray.size
}
inline fun BytePacketBuilder.writeIntLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long) = {it}, builder: BytePacketBuilder.() -> Unit): Int =
internal inline fun BytePacketBuilder.writeIntLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long) = {it}, builder: BytePacketBuilder.() -> Unit): Int =
BytePacketBuilder().apply(builder).build().use {
if (tag != null) writeUByte(tag)
val length = lengthOffset.invoke(it.remaining).coerceAtMostOrFail(0xFFFFFFFFL)
......@@ -47,7 +47,7 @@ inline fun BytePacketBuilder.writeIntLVPacket(tag: UByte? = null, lengthOffset:
return length.toInt()
}
inline fun BytePacketBuilder.writeShortLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long) = {it}, builder: BytePacketBuilder.() -> Unit): Int =
internal inline fun BytePacketBuilder.writeShortLVPacket(tag: UByte? = null, lengthOffset: ((Long) -> Long) = {it}, builder: BytePacketBuilder.() -> Unit): Int =
BytePacketBuilder().apply(builder).build().use {
if (tag != null) writeUByte(tag)
val length = lengthOffset.invoke(it.remaining).coerceAtMostOrFail(0xFFFFFFFFL)
......@@ -56,18 +56,16 @@ inline fun BytePacketBuilder.writeShortLVPacket(tag: UByte? = null, lengthOffset
return length.toInt()
}
inline fun BytePacketBuilder.writeShortLVString(str: String) = writeShortLVByteArray(str.toByteArray())
internal inline fun BytePacketBuilder.writeShortLVString(str: String) = writeShortLVByteArray(str.toByteArray())
fun BytePacketBuilder.writeHex(uHex: String) {
internal fun BytePacketBuilder.writeHex(uHex: String) {
uHex.split(" ").forEach {
if (it.isNotBlank()) {
writeUByte(it.toUByte(16))
}
}
}
/**
* 会使用 [ByteArrayPool] 缓存
*/
@OptIn(MiraiInternalAPI::class)
inline fun BytePacketBuilder.encryptAndWrite(key: ByteArray, encoder: BytePacketBuilder.() -> Unit) =
internal inline fun BytePacketBuilder.encryptAndWrite(key: ByteArray, encoder: BytePacketBuilder.() -> Unit) =
TEA.encrypt(BytePacketBuilder().apply(encoder).build(), key) { decrypted -> writeFully(decrypted) }
\ No newline at end of file
......@@ -32,10 +32,10 @@ internal actual class ECDHKeyPairImpl(
}
@Suppress("FunctionName")
actual fun ECDH() =
internal actual fun ECDH() =
ECDH(ECDH.generateKeyPair())
actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
internal actual class ECDH actual constructor(actual val keyPair: ECDHKeyPair) {
actual companion object {
actual val isECDHAvailable: Boolean
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment