Commit c8eac6af authored by Him188's avatar Him188

Move packet stuffs to mirai-core

parent 19d5c910
......@@ -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.*
......
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
)
\ No newline at end of file
......@@ -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.contact.Group
import net.mamoe.mirai.contact.Member
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
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.Group
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)
......
@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
\ No newline at end of file
annotation class NoLog
\ No newline at end of file
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)
@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
)
}
}
......
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"
}
@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()
}
}
......
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_UNSIGNED_LITERALS")
package net.mamoe.mirai.timpc.network.packet
package net.mamoe.mirai.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)
fun matchPacketId(value: UShort): PacketId =
IgnoredPacketIds.firstOrNull { it.value == value }
?: KnownPacketId.entries.firstOrNull { it.value.value == value }?.value
?: UnknownPacketId(value)
/**
* 包 ID.
*/
internal interface PacketId {
interface PacketId {
val value: UShort
val factory: PacketFactory<*, *>
}
......@@ -27,7 +25,7 @@ internal interface PacketId {
* 用于代表 `null`. 调用任何属性时都将会得到一个 [error]
*/
@Suppress("unused")
internal object NullPacketId : PacketId {
object NullPacketId : PacketId {
override val factory: PacketFactory<*, *> get() = error("uninitialized")
override val value: UShort get() = error("uninitialized")
override fun toString(): String = "NullPacketId"
......@@ -36,65 +34,43 @@ internal object NullPacketId : PacketId {
/**
* 未知的 [PacketId]
*/
internal inline class UnknownPacketId(override inline val value: UShort) : PacketId {
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 {
object IgnoredPacketIds : List<IgnoredPacketId> by {
listOf<UShort>(
).map { IgnoredPacketId(it.toUShort()) }
}()
internal inline class IgnoredPacketId constructor(override val value: UShort) : PacketId {
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),
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
}
override fun toString(): String = (factory::class.simpleName ?: this.name) + "(${value.toUHexString()})"
}
}
\ No newline at end of file
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