mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-14 07:10:09 +08:00
Move packet stuffs to mirai-core
This commit is contained in:
parent
19d5c910fd
commit
c8eac6aff4
@ -11,6 +11,9 @@ import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.ImageId0x03
|
||||
import net.mamoe.mirai.message.data.ImageId0x06
|
||||
import net.mamoe.mirai.network.packet.KnownPacketId
|
||||
import net.mamoe.mirai.network.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.network.packet.SessionKey
|
||||
import net.mamoe.mirai.qqAccount
|
||||
import net.mamoe.mirai.timpc.internal.RawGroupInfo
|
||||
import net.mamoe.mirai.timpc.network.GroupImpl
|
||||
@ -18,10 +21,10 @@ import net.mamoe.mirai.timpc.network.MemberImpl
|
||||
import net.mamoe.mirai.timpc.network.QQImpl
|
||||
import net.mamoe.mirai.timpc.network.TIMBotNetworkHandler
|
||||
import net.mamoe.mirai.timpc.network.handler.TemporaryPacketHandler
|
||||
import net.mamoe.mirai.timpc.network.packet.KnownPacketId
|
||||
import net.mamoe.mirai.timpc.network.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.SessionKey
|
||||
import net.mamoe.mirai.timpc.network.packet.action.*
|
||||
import net.mamoe.mirai.timpc.network.packet.event.EventPacketFactory
|
||||
import net.mamoe.mirai.timpc.network.packet.event.FriendOnlineStatusChangedPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.login.*
|
||||
import net.mamoe.mirai.timpc.utils.assertUnreachable
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
||||
@ -44,9 +47,41 @@ internal abstract class TIMPCBotBase constructor(
|
||||
logger: MiraiLogger?,
|
||||
context: CoroutineContext
|
||||
) : BotImpl<TIMBotNetworkHandler>(account, logger ?: DefaultLogger("Bot(" + account.id + ")"), context) {
|
||||
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
companion object {
|
||||
init {
|
||||
KnownPacketId.values() /* load id classes */
|
||||
KnownPacketId[0x0825u] = TouchPacket
|
||||
KnownPacketId[0x0828u] = RequestSessionPacket
|
||||
KnownPacketId[0x0836u] = SubmitPasswordPacket
|
||||
KnownPacketId[0x00BAu] = CaptchaPacket
|
||||
KnownPacketId[0x00CEu] = EventPacketFactory
|
||||
KnownPacketId[0x0017u] = EventPacketFactory
|
||||
KnownPacketId[0x0081u] = FriendOnlineStatusChangedPacket
|
||||
KnownPacketId[0x00ECu] = ChangeOnlineStatusPacket
|
||||
|
||||
KnownPacketId[0x0058u] = HeartbeatPacket
|
||||
KnownPacketId[0x001Du] = RequestSKeyPacket
|
||||
KnownPacketId[0x005Cu] = RequestAccountInfoPacket
|
||||
KnownPacketId[0x0002u] = GroupPacket
|
||||
KnownPacketId[0x00CDu] = SendFriendMessagePacket
|
||||
KnownPacketId[0x00A7u] = CanAddFriendPacket
|
||||
KnownPacketId[0x00A8u] = AddFriendPacket
|
||||
KnownPacketId[0x00AEu] = RequestFriendAdditionKeyPacket
|
||||
KnownPacketId[0x0388u] = GroupImagePacket
|
||||
KnownPacketId[0x0352u] = FriendImagePacket
|
||||
|
||||
KnownPacketId[0x0031u] = RequestProfileAvatarPacket
|
||||
KnownPacketId[0x003Cu] = RequestProfileDetailsPacket
|
||||
KnownPacketId[0x0126u] = QueryNicknamePacket
|
||||
|
||||
KnownPacketId[0x01BCu] = QueryPreviousNamePacket
|
||||
|
||||
KnownPacketId[0x003Eu] = QueryFriendRemarkPacket
|
||||
// 031F 查询 "新朋友" 记录
|
||||
|
||||
// @Suppress("DEPRECATION")
|
||||
// inline SUBMIT_IMAGE_FILE_NAME(0x01BDu, SubmitImageFilenamePacket),
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +104,7 @@ internal abstract class TIMPCBotBase constructor(
|
||||
reinitializeNetworkHandler(configuration, cause)
|
||||
logger.info("Reconnected successfully")
|
||||
return@launch
|
||||
} catch (e: LoginFailedException){
|
||||
} catch (e: LoginFailedException) {
|
||||
delay(configuration.reconnectPeriodMillis)
|
||||
}
|
||||
}
|
||||
|
@ -6,19 +6,19 @@ import kotlinx.coroutines.*
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.LoginResult
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.event.BroadcastControllable
|
||||
import net.mamoe.mirai.event.Cancellable
|
||||
import net.mamoe.mirai.event.Subscribable
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BotLoginSucceedEvent
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.LoginResult
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.qqAccount
|
||||
import net.mamoe.mirai.timpc.TIMPCBot
|
||||
import net.mamoe.mirai.timpc.network.handler.DataPacketSocketAdapter
|
||||
import net.mamoe.mirai.timpc.network.handler.TemporaryPacketHandler
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.login.*
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
@ -0,0 +1,97 @@
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
|
||||
import kotlinx.io.core.BytePacketBuilder
|
||||
import kotlinx.serialization.SerializationStrategy
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.jvm.JvmOverloads
|
||||
|
||||
|
||||
/**
|
||||
* 构造一个待发送给服务器的数据包.
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class, ExperimentalUnsignedTypes::class)
|
||||
@JvmOverloads
|
||||
inline fun PacketFactory<*, *>.buildOutgoingPacket(
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
headerSizeHint: Int = 0,
|
||||
block: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
|
||||
return buildOutgoingPacket0(name, id, sequenceId, headerSizeHint, TIMProtocol.head, TIMProtocol.ver, TIMProtocol.tail, block)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构造一个待发送给服务器的会话数据包.
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class, ExperimentalUnsignedTypes::class)
|
||||
@JvmOverloads
|
||||
inline fun PacketFactory<*, *>.buildSessionPacket(
|
||||
bot: Long,
|
||||
sessionKey: SessionKey,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
headerSizeHint: Int = 0,
|
||||
version: ByteArray = TIMProtocol.version0x02, // in packet body
|
||||
block: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return buildSessionPacket0(
|
||||
bot = bot,
|
||||
sessionKey = sessionKey,
|
||||
name = name,
|
||||
id = id,
|
||||
sequenceId = sequenceId,
|
||||
headerSizeHint = headerSizeHint,
|
||||
version = version,
|
||||
head = TIMProtocol.head,
|
||||
ver = TIMProtocol.ver,
|
||||
tail = TIMProtocol.tail,
|
||||
block = block
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造一个待发送给服务器的会话数据包.
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class, ExperimentalUnsignedTypes::class)
|
||||
@JvmOverloads
|
||||
fun <T> PacketFactory<*, *>.buildSessionProtoPacket(
|
||||
bot: Long,
|
||||
sessionKey: SessionKey,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
headerSizeHint: Int = 0,
|
||||
version: ByteArray = TIMProtocol.version0x04,
|
||||
head: Any,
|
||||
serializer: SerializationStrategy<T>,
|
||||
protoObj: T
|
||||
): OutgoingPacket = buildSessionProtoPacket0(
|
||||
bot = bot,
|
||||
sessionKey = sessionKey,
|
||||
name = name,
|
||||
id = id,
|
||||
sequenceId = sequenceId,
|
||||
headerSizeHint = headerSizeHint,
|
||||
version = version,
|
||||
head = head,
|
||||
serializer = serializer,
|
||||
protoObj = protoObj,
|
||||
packetHead = TIMProtocol.head,
|
||||
ver = TIMProtocol.ver,
|
||||
tail = TIMProtocol.tail
|
||||
)
|
@ -1,100 +0,0 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
|
||||
import net.mamoe.mirai.timpc.network.packet.action.*
|
||||
import net.mamoe.mirai.timpc.network.packet.event.EventPacketFactory
|
||||
import net.mamoe.mirai.timpc.network.packet.event.FriendOnlineStatusChangedPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.login.*
|
||||
import net.mamoe.mirai.utils.io.toUHexString
|
||||
|
||||
|
||||
/**
|
||||
* 通过 [value] 匹配一个 [IgnoredPacketId] 或 [KnownPacketId], 无匹配则返回一个 [UnknownPacketId].
|
||||
*/
|
||||
internal fun matchPacketId(value: UShort): PacketId =
|
||||
IgnoredPacketIds.firstOrNull { it.value == value } ?: KnownPacketId.values().firstOrNull { it.value == value } ?: UnknownPacketId(value)
|
||||
|
||||
/**
|
||||
* 包 ID.
|
||||
*/
|
||||
internal interface PacketId {
|
||||
val value: UShort
|
||||
val factory: PacketFactory<*, *>
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于代表 `null`. 调用任何属性时都将会得到一个 [error]
|
||||
*/
|
||||
@Suppress("unused")
|
||||
internal object NullPacketId : PacketId {
|
||||
override val factory: PacketFactory<*, *> get() = error("uninitialized")
|
||||
override val value: UShort get() = error("uninitialized")
|
||||
override fun toString(): String = "NullPacketId"
|
||||
}
|
||||
|
||||
/**
|
||||
* 未知的 [PacketId]
|
||||
*/
|
||||
internal inline class UnknownPacketId(override inline val value: UShort) : PacketId {
|
||||
override val factory: PacketFactory<*, *> get() = UnknownPacketFactory
|
||||
override fun toString(): String = "UnknownPacketId(${value.toUHexString()})"
|
||||
}
|
||||
|
||||
internal object IgnoredPacketIds : List<IgnoredPacketId> by {
|
||||
listOf<UShort>(
|
||||
).map { IgnoredPacketId(it.toUShort()) }
|
||||
}()
|
||||
|
||||
internal inline class IgnoredPacketId constructor(override val value: UShort) : PacketId {
|
||||
override val factory: PacketFactory<*, *> get() = IgnoredPacketFactory
|
||||
override fun toString(): String = "IgnoredPacketId(${value.toUHexString()})"
|
||||
}
|
||||
|
||||
/**
|
||||
* 已知的 [matchPacketId]. 所有在 Mirai 中实现过的包都会使用这些 Id
|
||||
*/
|
||||
@Suppress("unused")
|
||||
internal enum class KnownPacketId(override val value: UShort, override val factory: PacketFactory<*, *>) :
|
||||
PacketId {
|
||||
TOUCH(0x0825u, TouchPacket),
|
||||
SESSION_KEY(0x0828u, RequestSessionPacket),
|
||||
LOGIN(0x0836u, SubmitPasswordPacket),
|
||||
CAPTCHA(0x00BAu, CaptchaPacket),
|
||||
SERVER_EVENT_1(0x00CEu, EventPacketFactory),
|
||||
SERVER_EVENT_2(0x0017u, EventPacketFactory),
|
||||
FRIEND_ONLINE_STATUS_CHANGE(0x0081u, FriendOnlineStatusChangedPacket),
|
||||
CHANGE_ONLINE_STATUS(0x00ECu, ChangeOnlineStatusPacket),
|
||||
|
||||
HEARTBEAT(0x0058u, HeartbeatPacket),
|
||||
S_KEY(0x001Du, RequestSKeyPacket),
|
||||
ACCOUNT_INFO(0x005Cu, RequestAccountInfoPacket),
|
||||
GROUP_PACKET(0x0002u, GroupPacket),
|
||||
SEND_FRIEND_MESSAGE(0x00CDu, SendFriendMessagePacket),
|
||||
CAN_ADD_FRIEND(0x00A7u, CanAddFriendPacket),
|
||||
ADD_FRIEND(0x00A8u, AddFriendPacket),
|
||||
REQUEST_FRIEND_ADDITION_KEY(0x00AEu, RequestFriendAdditionKeyPacket),
|
||||
GROUP_IMAGE_ID(0x0388u, GroupImagePacket),
|
||||
FRIEND_IMAGE_ID(0x0352u, FriendImagePacket),
|
||||
|
||||
REQUEST_PROFILE_AVATAR(0x0031u, RequestProfileAvatarPacket),
|
||||
REQUEST_PROFILE_DETAILS(0x003Cu, RequestProfileDetailsPacket),
|
||||
QUERY_NICKNAME(0x0126u, QueryNicknamePacket),
|
||||
|
||||
QUERY_PREVIOUS_NAME(0x01BCu, QueryPreviousNamePacket),
|
||||
|
||||
QUERY_FRIEND_REMARK(0x003Eu, QueryFriendRemarkPacket)
|
||||
// 031F 查询 "新朋友" 记录
|
||||
|
||||
|
||||
// @Suppress("DEPRECATION")
|
||||
// inline SUBMIT_IMAGE_FILE_NAME(0x01BDu, SubmitImageFilenamePacket),
|
||||
|
||||
;
|
||||
|
||||
init {
|
||||
factory._id = this
|
||||
}
|
||||
|
||||
override fun toString(): String = (factory::class.simpleName ?: this.name) + "(${value.toUHexString()})"
|
||||
}
|
@ -8,8 +8,9 @@ import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.data.PreviousNameList
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
|
||||
|
@ -4,14 +4,15 @@ package net.mamoe.mirai.timpc.network.packet.action
|
||||
|
||||
import kotlinx.io.charsets.Charsets
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.data.ImageLink
|
||||
import net.mamoe.mirai.message.data.ImageId
|
||||
import net.mamoe.mirai.message.data.ImageId0x06
|
||||
import net.mamoe.mirai.message.data.requireLength
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.data.ImageLink
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
|
@ -5,8 +5,8 @@ package net.mamoe.mirai.timpc.network.packet.action
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketId
|
||||
import net.mamoe.mirai.timpc.network.packet.SessionPacketFactory
|
||||
import net.mamoe.mirai.network.packet.PacketId
|
||||
import net.mamoe.mirai.network.packet.SessionPacketFactory
|
||||
|
||||
|
||||
// 0001
|
||||
|
@ -7,8 +7,9 @@ import kotlinx.io.core.writeFully
|
||||
import kotlinx.io.core.writeUByte
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
|
||||
/**
|
||||
|
@ -11,7 +11,8 @@ import net.mamoe.mirai.message.data.requireLength
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.data.ImageLink
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionProtoPacket
|
||||
import net.mamoe.mirai.timpc.utils.assertUnreachable
|
||||
import net.mamoe.mirai.utils.ExternalImage
|
||||
import net.mamoe.mirai.utils.io.toUHexString
|
||||
|
@ -6,17 +6,17 @@ import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.contact.GroupInternalId
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.contact.groupInternalId
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.internal.toPacket
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.internal.RawGroupInfo
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.timpc.utils.unsupportedFlag
|
||||
import net.mamoe.mirai.timpc.utils.unsupportedType
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
import kotlin.collections.mutableMapOf
|
||||
import kotlin.collections.set
|
||||
|
||||
|
||||
|
@ -5,10 +5,11 @@ package net.mamoe.mirai.timpc.network.packet.action
|
||||
import io.ktor.util.date.GMTDate
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.data.Gender
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.data.Profile
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
inline class AvatarLink(val value: String) : Packet
|
||||
|
@ -6,7 +6,8 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.FriendNameRemark
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.io.readUShortLVString
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
import net.mamoe.mirai.utils.io.writeZero
|
||||
|
@ -5,8 +5,9 @@ package net.mamoe.mirai.timpc.network.packet.action
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.io.writeZero
|
||||
|
||||
class FriendList : Packet
|
||||
|
@ -7,8 +7,9 @@ import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.internal.toPacket
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
import net.mamoe.mirai.utils.md5
|
||||
|
||||
|
@ -6,7 +6,7 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.io.readBoolean
|
||||
|
||||
|
||||
|
@ -6,9 +6,10 @@ import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMBotNetworkHandler
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.qqAccount
|
||||
import net.mamoe.mirai.timpc.network.packet.buildSessionPacket
|
||||
import net.mamoe.mirai.utils.io.readIoBuffer
|
||||
|
||||
/**
|
||||
|
@ -6,7 +6,7 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.event.events.ReceiveFriendAddRequestEvent
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.io.readQQ
|
||||
import net.mamoe.mirai.utils.io.readUShortLVString
|
||||
|
||||
|
@ -4,10 +4,9 @@ package net.mamoe.mirai.timpc.network.packet.event
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readUInt
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.io.readQQ
|
||||
|
||||
|
||||
|
@ -5,12 +5,10 @@ package net.mamoe.mirai.timpc.network.packet.event
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readUByte
|
||||
import kotlinx.io.core.readUInt
|
||||
import net.mamoe.mirai.event.events.FriendStatusChanged
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.timpc.network.packet.KnownPacketId
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketId
|
||||
import net.mamoe.mirai.timpc.network.packet.SessionPacketFactory
|
||||
import net.mamoe.mirai.network.packet.PacketId
|
||||
import net.mamoe.mirai.network.packet.SessionPacketFactory
|
||||
import net.mamoe.mirai.utils.OnlineStatus
|
||||
import net.mamoe.mirai.utils.io.readQQ
|
||||
|
||||
|
@ -5,7 +5,7 @@ package net.mamoe.mirai.timpc.network.packet.event
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.io.debugPrint
|
||||
|
||||
|
||||
|
@ -5,11 +5,11 @@ package net.mamoe.mirai.timpc.network.packet.event
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.io.readQQ
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.data.EventPacket
|
||||
import net.mamoe.mirai.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.io.readQQ
|
||||
|
||||
|
||||
data class MemberPermissionChangePacket(
|
||||
|
@ -7,7 +7,7 @@ import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.message.GroupMessage
|
||||
import net.mamoe.mirai.message.internal.readMessageChain
|
||||
import net.mamoe.mirai.message.FriendMessage
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.network.packet.PacketVersion
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
|
@ -5,11 +5,13 @@ package net.mamoe.mirai.timpc.network.packet.login
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
internal object CaptchaKey : DecrypterByteArray, DecrypterType<CaptchaKey> {
|
||||
internal object CaptchaKey : DecrypterByteArray,
|
||||
DecrypterType<CaptchaKey> {
|
||||
override val value: ByteArray = TIMProtocol.key00BA
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,9 @@ import kotlinx.io.core.writeFully
|
||||
import kotlinx.io.core.writeUByte
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.OnlineStatus
|
||||
import net.mamoe.mirai.utils.io.writeHex
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
@ -16,7 +17,9 @@ import net.mamoe.mirai.utils.io.writeQQ
|
||||
/**
|
||||
* 改变在线状态: "我在线上", "隐身" 等
|
||||
*/
|
||||
internal object ChangeOnlineStatusPacket : PacketFactory<ChangeOnlineStatusPacket.ChangeOnlineStatusResponse, NoDecrypter>(NoDecrypter) {
|
||||
internal object ChangeOnlineStatusPacket : PacketFactory<ChangeOnlineStatusPacket.ChangeOnlineStatusResponse, NoDecrypter>(
|
||||
NoDecrypter
|
||||
) {
|
||||
operator fun invoke(
|
||||
bot: Long,
|
||||
sessionKey: SessionKey,
|
||||
|
@ -7,8 +7,9 @@ import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.event.Subscribable
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.io.writeHex
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
|
||||
|
@ -7,12 +7,14 @@ import net.mamoe.mirai.data.Gender
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.LoginResult
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.*
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
internal object ShareKey : DecrypterByteArray, DecrypterType<ShareKey> {
|
||||
internal object ShareKey : DecrypterByteArray,
|
||||
DecrypterType<ShareKey> {
|
||||
override val value: ByteArray = TIMProtocol.shareKey
|
||||
}
|
||||
|
||||
|
@ -7,8 +7,9 @@ import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
internal inline class SKey(
|
||||
|
@ -5,8 +5,11 @@ package net.mamoe.mirai.timpc.network.packet.login
|
||||
import kotlinx.io.core.*
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.packet.PacketFactory
|
||||
import net.mamoe.mirai.network.packet.PacketId
|
||||
import net.mamoe.mirai.network.packet.SessionKey
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
import net.mamoe.mirai.utils.localIpAddress
|
||||
|
||||
|
@ -6,13 +6,15 @@ import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readBytes
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.buildOutgoingPacket
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
internal object TouchKey : DecrypterByteArray, DecrypterType<TouchKey> {
|
||||
internal object TouchKey : DecrypterByteArray,
|
||||
DecrypterType<TouchKey> {
|
||||
override val value: ByteArray = TIMProtocol.touchKey
|
||||
}
|
||||
|
||||
|
@ -16,13 +16,12 @@ import kotlinx.serialization.internal.ArrayListSerializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.timpc.TIMPC
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.timpc.network.packet.*
|
||||
import net.mamoe.mirai.timpc.network.packet.event.FriendOnlineStatusChangedPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.event.IgnoredEventPacket
|
||||
import net.mamoe.mirai.timpc.network.packet.login.CaptchaKey
|
||||
import net.mamoe.mirai.timpc.network.packet.login.ShareKey
|
||||
import net.mamoe.mirai.timpc.network.packet.login.TouchKey
|
||||
import net.mamoe.mirai.timpc.network.packet.login.*
|
||||
import net.mamoe.mirai.utils.DecryptionFailedException
|
||||
import net.mamoe.mirai.utils.decryptBy
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
@ -181,7 +180,8 @@ internal object PacketDebugger {
|
||||
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
|
||||
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
|
||||
*/
|
||||
val sessionKey: SessionKey = SessionKey("95 F3 24 8E 7B B6 62 AA 98 C0 EE 45 CE CE 2B 69".hexToBytes())
|
||||
val sessionKey: SessionKey =
|
||||
SessionKey("95 F3 24 8E 7B B6 62 AA 98 C0 EE 45 CE CE 2B 69".hexToBytes())
|
||||
// TODO: 2019/12/7 无法访问 internal 是 kotlin bug, KT-34849
|
||||
|
||||
/**
|
||||
@ -194,9 +194,9 @@ internal object PacketDebugger {
|
||||
val recorder: Recorder? = Recorder()
|
||||
|
||||
val IgnoredPacketIdList: List<PacketId> = listOf(
|
||||
KnownPacketId.FRIEND_ONLINE_STATUS_CHANGE,
|
||||
KnownPacketId.CHANGE_ONLINE_STATUS,
|
||||
KnownPacketId.HEARTBEAT
|
||||
KnownPacketId.get<FriendOnlineStatusChangedPacket>(),
|
||||
KnownPacketId.get<ChangeOnlineStatusPacket>(),
|
||||
KnownPacketId.get<HeartbeatPacket>()
|
||||
)
|
||||
|
||||
suspend fun dataReceived(data: ByteArray) {
|
||||
@ -204,10 +204,10 @@ internal object PacketDebugger {
|
||||
//println("raw = " + data.toUHexString())
|
||||
data.read {
|
||||
discardExact(3)
|
||||
val id = matchPacketId(readUShort())
|
||||
val id = net.mamoe.mirai.network.packet.matchPacketId(readUShort())
|
||||
val sequenceId = readUShort()
|
||||
val packetQQ = readQQ()
|
||||
if (id == KnownPacketId.HEARTBEAT || (qq != null && packetQQ != qq))
|
||||
if (id == KnownPacketId.get<HeartbeatPacket>() || (qq != null && packetQQ != qq))
|
||||
return@read
|
||||
|
||||
if (IgnoredPacketIdList.contains(id)) {
|
||||
@ -301,7 +301,7 @@ internal object PacketDebugger {
|
||||
// 3E 03 3F A2 02 00 00 00 01 2E 01 00 00 69 35
|
||||
|
||||
discardExact(3)//head
|
||||
val id = matchPacketId(readUShort())
|
||||
val id = net.mamoe.mirai.network.packet.matchPacketId(readUShort())
|
||||
val sequence = readUShort().toUHexString()
|
||||
if (IgnoredPacketIdList.contains(id)) {
|
||||
return
|
||||
|
@ -3,8 +3,8 @@ package packetdebugger
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.discardExact
|
||||
import kotlinx.io.core.readUShort
|
||||
import net.mamoe.mirai.timpc.network.packet.PacketId
|
||||
import net.mamoe.mirai.timpc.network.packet.matchPacketId
|
||||
import net.mamoe.mirai.network.packet.PacketId
|
||||
import net.mamoe.mirai.network.packet.matchPacketId
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
|
@ -19,14 +19,18 @@ import kotlin.coroutines.CoroutineContext
|
||||
*/
|
||||
@MiraiInternalAPI
|
||||
abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
override val account: BotAccount,
|
||||
override val logger: MiraiLogger = DefaultLogger("Bot(" + account.id + ")"),
|
||||
account: BotAccount,
|
||||
logger: MiraiLogger?,
|
||||
context: CoroutineContext
|
||||
) : Bot(), CoroutineScope {
|
||||
private val supervisorJob = SupervisorJob(context[Job])
|
||||
override val coroutineContext: CoroutineContext =
|
||||
context + supervisorJob + CoroutineExceptionHandler { _, e -> e.logStacktrace("An exception was thrown under a coroutine of Bot") }
|
||||
|
||||
@Suppress("CanBePrimaryConstructorProperty") // for logger
|
||||
override val account: BotAccount = account
|
||||
override val logger: MiraiLogger = logger ?: DefaultLogger("Bot(" + account.id + ")")
|
||||
|
||||
init {
|
||||
@Suppress("LeakingThis")
|
||||
instances.addLast(this)
|
||||
|
@ -1,6 +1,6 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "unused")
|
||||
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
package net.mamoe.mirai.network.packet
|
||||
|
||||
/**
|
||||
* 包的最后一次修改时间, 和分析时使用的 TIM 版本
|
||||
@ -8,11 +8,11 @@ package net.mamoe.mirai.timpc.network.packet
|
||||
@MustBeDocumented
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
internal annotation class PacketVersion(val date: String, val timVersion: String)
|
||||
annotation class PacketVersion(val date: String, val timVersion: String)
|
||||
|
||||
/**
|
||||
* 带有这个注解的 [Packet] 将不会被记录在 log 中.
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
internal annotation class NoLog
|
||||
annotation class NoLog
|
@ -1,26 +1,23 @@
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
package net.mamoe.mirai.network.packet
|
||||
|
||||
import kotlinx.io.core.BytePacketBuilder
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.IoBuffer
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.utils.decryptBy
|
||||
import net.mamoe.mirai.utils.encryptBy
|
||||
import net.mamoe.mirai.utils.io.encryptAndWrite
|
||||
|
||||
|
||||
/**
|
||||
* 会话密匙
|
||||
*/
|
||||
internal inline class SessionKey(override val value: ByteArray) : DecrypterByteArray {
|
||||
inline class SessionKey(override val value: ByteArray) : DecrypterByteArray {
|
||||
companion object Type : DecrypterType<SessionKey>
|
||||
}
|
||||
|
||||
/**
|
||||
* [ByteArray] 解密器
|
||||
*/
|
||||
@PublishedApi
|
||||
internal interface DecrypterByteArray : Decrypter {
|
||||
interface DecrypterByteArray : Decrypter {
|
||||
val value: ByteArray
|
||||
override fun decrypt(input: ByteReadPacket): ByteReadPacket = input.decryptBy(value)
|
||||
}
|
||||
@ -28,7 +25,7 @@ internal interface DecrypterByteArray : Decrypter {
|
||||
/**
|
||||
* [IoBuffer] 解密器
|
||||
*/
|
||||
internal interface DecrypterIoBuffer : Decrypter {
|
||||
interface DecrypterIoBuffer : Decrypter {
|
||||
val value: IoBuffer
|
||||
override fun decrypt(input: ByteReadPacket): ByteReadPacket = input.decryptBy(value)
|
||||
}
|
||||
@ -36,27 +33,28 @@ internal interface DecrypterIoBuffer : Decrypter {
|
||||
/**
|
||||
* 连接在一起的解密器
|
||||
*/
|
||||
internal inline class LinkedDecrypter(inline val block: (ByteReadPacket) -> ByteReadPacket) : Decrypter {
|
||||
inline class LinkedDecrypter(inline val block: (ByteReadPacket) -> ByteReadPacket) : Decrypter {
|
||||
override fun decrypt(input: ByteReadPacket): ByteReadPacket = block(input)
|
||||
}
|
||||
|
||||
internal object NoDecrypter : Decrypter, DecrypterType<NoDecrypter> {
|
||||
object NoDecrypter : Decrypter,
|
||||
DecrypterType<NoDecrypter> {
|
||||
override fun decrypt(input: ByteReadPacket): ByteReadPacket = input
|
||||
}
|
||||
|
||||
/**
|
||||
* 解密器
|
||||
*/
|
||||
internal interface Decrypter {
|
||||
*/
|
||||
interface Decrypter {
|
||||
fun decrypt(input: ByteReadPacket): ByteReadPacket
|
||||
/**
|
||||
* 连接后将会先用 this 解密, 再用 [another] 解密
|
||||
*/
|
||||
operator fun plus(another: Decrypter): Decrypter = LinkedDecrypter { another.decrypt(this.decrypt(it)) }
|
||||
operator fun plus(another: Decrypter): Decrypter =
|
||||
LinkedDecrypter { another.decrypt(this.decrypt(it)) }
|
||||
}
|
||||
|
||||
interface DecrypterType<D : Decrypter>
|
||||
|
||||
internal interface DecrypterType<D : Decrypter>
|
||||
|
||||
@PublishedApi
|
||||
internal inline fun BytePacketBuilder.encryptAndWrite(key: DecrypterByteArray, encoder: BytePacketBuilder.() -> Unit) =
|
||||
inline fun BytePacketBuilder.encryptAndWrite(key: DecrypterByteArray, encoder: BytePacketBuilder.() -> Unit) =
|
||||
this.encryptAndWrite(key.value, encoder)
|
@ -1,13 +1,13 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS", "unused", "MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
package net.mamoe.mirai.network.packet
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.serialization.SerializationStrategy
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.timpc.network.TIMProtocol
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.hexToBytes
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
@ -18,11 +18,11 @@ import kotlin.jvm.JvmOverloads
|
||||
/**
|
||||
* 待发送给服务器的数据包. 它代表着一个 [ByteReadPacket],
|
||||
*/
|
||||
internal class OutgoingPacket(
|
||||
class OutgoingPacket(
|
||||
name: String?,
|
||||
val packetId: PacketId,
|
||||
val sequenceId: UShort,
|
||||
internal val delegate: ByteReadPacket
|
||||
val delegate: ByteReadPacket
|
||||
) : Packet {
|
||||
val name: String by lazy {
|
||||
name ?: packetId.toString()
|
||||
@ -35,7 +35,9 @@ internal class OutgoingPacket(
|
||||
*
|
||||
* @param TPacket invariant
|
||||
*/
|
||||
internal abstract class SessionPacketFactory<TPacket : Packet> : PacketFactory<TPacket, SessionKey>(SessionKey) {
|
||||
abstract class SessionPacketFactory<TPacket : Packet> : PacketFactory<TPacket, SessionKey>(
|
||||
SessionKey
|
||||
) {
|
||||
/**
|
||||
* 在 [BotNetworkHandler] 下处理这个包. 广播事件等.
|
||||
*/
|
||||
@ -45,13 +47,16 @@ internal abstract class SessionPacketFactory<TPacket : Packet> : PacketFactory<T
|
||||
/**
|
||||
* 构造一个待发送给服务器的数据包.
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class)
|
||||
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class)
|
||||
@JvmOverloads
|
||||
internal inline fun PacketFactory<*, *>.buildOutgoingPacket(
|
||||
inline fun PacketFactory<*, *>.buildOutgoingPacket0(
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
headerSizeHint: Int = 0,
|
||||
head: ByteArray,
|
||||
ver: ByteArray,
|
||||
tail: ByteArray,
|
||||
block: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket {
|
||||
contract {
|
||||
@ -60,12 +65,12 @@ internal inline fun PacketFactory<*, *>.buildOutgoingPacket(
|
||||
|
||||
BytePacketBuilder(headerSizeHint).use {
|
||||
with(it) {
|
||||
writeFully(TIMProtocol.head)
|
||||
writeFully(TIMProtocol.ver)
|
||||
writeFully(head)
|
||||
writeFully(ver)
|
||||
writeUShort(id.value)
|
||||
writeUShort(sequenceId)
|
||||
block(this)
|
||||
writeFully(TIMProtocol.tail)
|
||||
writeFully(tail)
|
||||
}
|
||||
return OutgoingPacket(name, id, sequenceId, it.build())
|
||||
}
|
||||
@ -75,22 +80,33 @@ internal inline fun PacketFactory<*, *>.buildOutgoingPacket(
|
||||
/**
|
||||
* 构造一个待发送给服务器的会话数据包.
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class)
|
||||
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class)
|
||||
@JvmOverloads
|
||||
internal inline fun PacketFactory<*, *>.buildSessionPacket(
|
||||
inline fun PacketFactory<*, *>.buildSessionPacket0(
|
||||
bot: Long,
|
||||
sessionKey: SessionKey,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
headerSizeHint: Int = 0,
|
||||
version: ByteArray = TIMProtocol.version0x02,
|
||||
version: ByteArray, // in packet body
|
||||
head: ByteArray,
|
||||
ver: ByteArray, // in packet head
|
||||
tail: ByteArray,
|
||||
block: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket {
|
||||
contract {
|
||||
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return buildOutgoingPacket(name, id, sequenceId, headerSizeHint) {
|
||||
return buildOutgoingPacket0(
|
||||
name = name,
|
||||
id = id,
|
||||
sequenceId = sequenceId,
|
||||
headerSizeHint = headerSizeHint,
|
||||
head = head,
|
||||
ver = ver,
|
||||
tail = tail
|
||||
) {
|
||||
writeQQ(bot)
|
||||
writeFully(version)
|
||||
encryptAndWrite(sessionKey) {
|
||||
@ -102,22 +118,25 @@ internal inline fun PacketFactory<*, *>.buildSessionPacket(
|
||||
/**
|
||||
* 构造一个待发送给服务器的会话数据包.
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class)
|
||||
@UseExperimental(ExperimentalContracts::class, MiraiInternalAPI::class)
|
||||
@JvmOverloads
|
||||
internal fun <T> PacketFactory<*, *>.buildSessionProtoPacket(
|
||||
fun <T> PacketFactory<*, *>.buildSessionProtoPacket0(
|
||||
bot: Long,
|
||||
sessionKey: SessionKey,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
headerSizeHint: Int = 0,
|
||||
version: ByteArray = TIMProtocol.version0x04,
|
||||
version: ByteArray,
|
||||
head: Any,
|
||||
serializer: SerializationStrategy<T>,
|
||||
protoObj: T
|
||||
protoObj: T,
|
||||
packetHead: ByteArray,
|
||||
ver: ByteArray, // in packet head
|
||||
tail: ByteArray
|
||||
): OutgoingPacket {
|
||||
require(head is ByteArray || head is UByteArray || head is String) { "Illegal head type" }
|
||||
return buildOutgoingPacket(name, id, sequenceId, headerSizeHint) {
|
||||
return buildOutgoingPacket0(name, id, sequenceId, headerSizeHint, head = packetHead, ver = ver, tail = tail) {
|
||||
writeQQ(bot)
|
||||
writeFully(version)
|
||||
encryptAndWrite(sessionKey) {
|
||||
@ -136,17 +155,20 @@ internal fun <T> PacketFactory<*, *>.buildSessionProtoPacket(
|
||||
writeFully(head)
|
||||
writeFully(proto)
|
||||
}
|
||||
is String -> buildSessionProtoPacket(
|
||||
bot,
|
||||
sessionKey,
|
||||
name,
|
||||
id,
|
||||
sequenceId,
|
||||
headerSizeHint,
|
||||
version,
|
||||
head.hexToBytes(),
|
||||
serializer,
|
||||
protoObj
|
||||
is String -> buildSessionProtoPacket0(
|
||||
bot = bot,
|
||||
sessionKey = sessionKey,
|
||||
name = name,
|
||||
id = id,
|
||||
sequenceId = sequenceId,
|
||||
headerSizeHint = headerSizeHint,
|
||||
version = version,
|
||||
head = head.hexToBytes(),
|
||||
serializer = serializer,
|
||||
protoObj = protoObj,
|
||||
packetHead = packetHead,
|
||||
ver = ver,
|
||||
tail = tail
|
||||
)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
package net.mamoe.mirai.network.packet
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.readBytes
|
||||
@ -8,18 +8,18 @@ import net.mamoe.mirai.utils.io.toUHexString
|
||||
/**
|
||||
* 被忽略的数据包.
|
||||
*/
|
||||
internal inline class IgnoredPacket(internal val id: PacketId) : Packet
|
||||
inline class IgnoredPacket(internal val id: PacketId) : Packet
|
||||
|
||||
/**
|
||||
* 未知的包.
|
||||
*/
|
||||
internal class UnknownPacket(val id: PacketId, val body: ByteReadPacket) : Packet {
|
||||
class UnknownPacket(val id: PacketId, val body: ByteReadPacket) : Packet {
|
||||
override fun toString(): String = "UnknownPacket(${id.value.toUHexString()})\nbody=${body.readBytes().toUHexString()}"
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅用于替换类型应为 [Unit] 的情况
|
||||
*/
|
||||
internal object NoPacket : Packet {
|
||||
object NoPacket : Packet {
|
||||
override fun toString(): String = "NoPacket"
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
package net.mamoe.mirai.timpc.network.packet
|
||||
package net.mamoe.mirai.network.packet
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
@ -11,6 +11,7 @@ import kotlinx.serialization.DeserializationStrategy
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.ByteArrayPool
|
||||
import net.mamoe.mirai.utils.io.debugPrint
|
||||
import net.mamoe.mirai.utils.io.read
|
||||
@ -24,7 +25,7 @@ import net.mamoe.mirai.utils.readProtoMap
|
||||
* @param TPacket 服务器回复包解析结果
|
||||
* @param TDecrypter 服务器回复包解密器
|
||||
*/
|
||||
internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypter>(val decrypterType: DecrypterType<TDecrypter>) {
|
||||
abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypter>(val decrypterType: DecrypterType<TDecrypter>) {
|
||||
|
||||
@Suppress("PropertyName")
|
||||
internal var _id: PacketId = NullPacketId
|
||||
@ -64,8 +65,8 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
|
||||
companion object {
|
||||
private val sequenceIdInternal = atomic(1)
|
||||
|
||||
@PublishedApi
|
||||
internal fun atomicNextSequenceId(): UShort = sequenceIdInternal.getAndIncrement().toUShort()
|
||||
@MiraiInternalAPI
|
||||
fun atomicNextSequenceId(): UShort = sequenceIdInternal.getAndIncrement().toUShort()
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,76 @@
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
|
||||
|
||||
package net.mamoe.mirai.network.packet
|
||||
|
||||
import net.mamoe.mirai.utils.io.toUHexString
|
||||
|
||||
|
||||
/**
|
||||
* 通过 [value] 匹配一个 [IgnoredPacketId] 或 [KnownPacketId], 无匹配则返回一个 [UnknownPacketId].
|
||||
*/
|
||||
fun matchPacketId(value: UShort): PacketId =
|
||||
IgnoredPacketIds.firstOrNull { it.value == value }
|
||||
?: KnownPacketId.entries.firstOrNull { it.value.value == value }?.value
|
||||
?: UnknownPacketId(value)
|
||||
|
||||
/**
|
||||
* 包 ID.
|
||||
*/
|
||||
interface PacketId {
|
||||
val value: UShort
|
||||
val factory: PacketFactory<*, *>
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于代表 `null`. 调用任何属性时都将会得到一个 [error]
|
||||
*/
|
||||
@Suppress("unused")
|
||||
object NullPacketId : PacketId {
|
||||
override val factory: PacketFactory<*, *> get() = error("uninitialized")
|
||||
override val value: UShort get() = error("uninitialized")
|
||||
override fun toString(): String = "NullPacketId"
|
||||
}
|
||||
|
||||
/**
|
||||
* 未知的 [PacketId]
|
||||
*/
|
||||
inline class UnknownPacketId(override inline val value: UShort) : PacketId {
|
||||
override val factory: PacketFactory<*, *> get() = UnknownPacketFactory
|
||||
override fun toString(): String = "UnknownPacketId(${value.toUHexString()})"
|
||||
}
|
||||
|
||||
object IgnoredPacketIds : List<IgnoredPacketId> by {
|
||||
listOf<UShort>(
|
||||
).map { IgnoredPacketId(it.toUShort()) }
|
||||
}()
|
||||
|
||||
inline class IgnoredPacketId constructor(override val value: UShort) : PacketId {
|
||||
override val factory: PacketFactory<*, *> get() = IgnoredPacketFactory
|
||||
override fun toString(): String = "IgnoredPacketId(${value.toUHexString()})"
|
||||
}
|
||||
|
||||
class KnownPacketId(override val value: UShort, override val factory: PacketFactory<*, *>) : PacketId {
|
||||
companion object : MutableMap<UShort, KnownPacketId> by mutableMapOf() {
|
||||
operator fun set(key: UShort, factory: PacketFactory<*, *>) {
|
||||
this[key] = KnownPacketId(key, factory)
|
||||
}
|
||||
|
||||
inline fun <reified PF : PacketFactory<*, *>> getOrNull(): KnownPacketId? {
|
||||
val clazz = PF::class
|
||||
this.forEach {
|
||||
if (clazz.isInstance(it.value)) {
|
||||
return it.value
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
inline fun <reified PF : PacketFactory<*, *>> get(): KnownPacketId = getOrNull<PF>() ?: throw NoSuchElementException()
|
||||
}
|
||||
|
||||
override fun toString(): String = (factory::class.simpleName ?: factory::class.simpleName) + "(${value.toUHexString()})"
|
||||
|
||||
init {
|
||||
factory._id = this
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user