Commit b02a5a79 authored by Him188's avatar Him188

Simplify packet structure

parent 0f1328ef
......@@ -94,10 +94,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
override suspend fun awaitDisconnection() {
while (true) {
delay(100)
// TODO: 2019/12/31
}
supervisor.join()
}
override fun dispose(cause: Throwable?) {
......
......@@ -22,11 +22,6 @@ internal class OutgoingPacket constructor(
name: String?,
val packetId: PacketId,
val sequenceId: Int,
// TODO: 2020/1/6 这个 sequenceId 设计有问题.
// 02 03 包里面的那个应该并不是 sequenceId.
// 它应该是固定的 0x001.
// 应该在这里填入 SSO 的 sequenceId.
// 同时考虑修改名称. 这可能不应该叫做 SSO. 它在全程都有
val delegate: ByteReadPacket
) {
val name: String by lazy {
......@@ -47,30 +42,40 @@ private val EMPTY_BYTE_ARRAY = ByteArray(0)
* int extra data size + 4
* byte[] extra data
* byte 0
* int [uinAccount].length + 4
* int uinAccount.length + 4
* byte[] uinAccount
*
* byte[] body encrypted by 16 zero
*/
internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
uinAccount: String,
client: QQAndroidClient,
subAppId: Long,
extraData: ByteArray = EMPTY_BYTE_ARRAY,
name: String? = null,
id: PacketId = this.id,
ssoExtraData: ByteReadPacket = BRP_STUB,
sequenceId: Int = PacketFactory.atomicNextSequenceId(),
body: BytePacketBuilder.() -> Unit
body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket = OutgoingPacket(name, id, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x00_00_00_0A)
writeByte(0x02)
writeInt(extraData.size + 4)
writeFully(extraData)
extraData.let {
writeInt(it.size + 4)
writeFully(it)
}
writeByte(0x00)
writeInt(uinAccount.length + 4)
writeStringUtf8(uinAccount)
client.account.id.toString().let {
writeInt(it.length + 4)
writeStringUtf8(it)
}
encryptAndWrite(KEY_16_ZEROS, body)
encryptAndWrite(KEY_16_ZEROS) {
writeLoginSsoPacket(client, subAppId, id, ssoExtraData, sequenceId) {
body(sequenceId)
}
}
}
})
......@@ -79,20 +84,38 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
/**
* The second outermost packet for login
*
* int headRemaining.size+4
* int sequenceId
* int subAppId
* int subAppId
* hex "01 00 00 00 00 00 00 00 00 00 01 00" // unknown values
* int extraData.size+4
* byte[] extraData
* int commandName.length+4
* byte[] commandName
* int 4+4
* int 0x02B05B8B
* int imei.length+4
* byte[] imei
* int 0+4
* int ksid.length+4
* byte[] ksid
* int 0+4
*
* int bodyRemaining.size+4
* byte[] body()
*/
@UseExperimental(MiraiInternalAPI::class)
internal inline fun BytePacketBuilder.writeLoginSsoPacket(
private inline fun BytePacketBuilder.writeLoginSsoPacket(
client: QQAndroidClient,
subAppId: Long,
packetId: PacketId,
extraData: ByteReadPacket = BRP_STUB,
body: BytePacketBuilder.(ssoSequenceId: Int) -> Unit
sequenceId: Int,
body: BytePacketBuilder.() -> Unit
) {
val ssoSequenceId = client.nextSsoSequenceId()
// head
writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(ssoSequenceId)
writeInt(sequenceId)
writeInt(subAppId.toInt())
writeInt(subAppId.toInt())
writeHex("01 00 00 00 00 00 00 00 00 00 01 00")
......@@ -126,9 +149,7 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
}
// body
writeIntLVPacket(lengthOffset = { it + 4 }) {
body(ssoSequenceId)
}
writeIntLVPacket(lengthOffset = { it + 4 }, builder = body)
}
/**
......@@ -245,7 +266,7 @@ internal interface EncryptMethodECDH : EncryptMethod {
* byte 2 // head flag
* short 27 + 2 + remaining.length
* ushort client.protocolVersion // const 8001
* ushort sequenceId
* ushort 0x0001
* uint client.account.id
* byte 3 // const
* ubyte encryptMethod.value // [EncryptMethod]
......@@ -257,7 +278,7 @@ internal interface EncryptMethodECDH : EncryptMethod {
* byte 3 // tail
*/
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
internal inline fun BytePacketBuilder.writeRequestPacket(
internal inline fun BytePacketBuilder.writeOicqRequestPacket(
client: QQAndroidClient,
encryptMethod: EncryptMethod,
packetId: PacketId,
......@@ -271,7 +292,7 @@ internal inline fun BytePacketBuilder.writeRequestPacket(
writeByte(0x02) // head
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
writeShort(client.protocolVersion)
writeShort(1)
writeShort(1) // const??
writeShort(packetId.commandId.toShort())
writeQQ(client.account.id)
writeByte(3) // originally const
......
......@@ -21,17 +21,17 @@ class LoginPacketDecrypter(override val value: ByteArray) : DecrypterByteArray {
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, LoginPacketDecrypter>(LoginPacketDecrypter) {
init {
this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login", subCommandId = 9)
this._id = PacketId(commandId = 0x0810, commandName = "wtlogin.login")
}
operator fun invoke(
client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client.account.id.toString()) {
object SubCommand9 {
val appId = 16L
val subAppId = 537062845L
writeLoginSsoPacket(client, subAppId, id) { ssoSequenceId ->
writeRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
operator fun invoke(
client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, 537062845L) { sequenceId ->
writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
writeShort(9) // subCommand
writeShort(LoginType.PASSWORD.value.toShort())
......@@ -100,7 +100,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
// ignored t16a because array5 is null
t154(ssoSequenceId)
t154(sequenceId)
t141(client.device.simInfo, client.networkType, client.device.apn)
t8(2052)
......@@ -129,8 +129,10 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
t187(client.device.macAddress)
t188(client.device.androidId)
if (client.device.imsiMd5.isNotEmpty()) {
t194(client.device.imsiMd5)
val imsi = client.device.imsiMd5
if (imsi.isNotEmpty()) {
t194(imsi)
}
t191()
......@@ -158,32 +160,36 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
// ignored t318 because not logging in by QR
}
}
suspend fun ByteReadPacket.decode(bot: QQAndroidBot): LoginPacketResponse {
TODO("not implemented")
}
}
class LoginPacketResponse : Packet
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): LoginPacketResponse {
TODO("not implemented")
return when (val subCommand = readShort().toInt()) {
9 -> SubCommand9.run { decode(bot) }
else -> error("Unknown subCommand: $subCommand")
}
}
}
@Suppress("FunctionName")
internal fun PacketId(commandId: Int, commandName: String, subCommandId: Int) = object : PacketId {
internal fun PacketId(commandId: Int, commandName: String) = object : PacketId {
override val commandId: Int get() = commandId
override val commandName: String get() = commandName
override val subCommandId: Int get() = subCommandId
}
internal interface PacketId {
val commandId: Int // ushort actually
val commandName: String
val subCommandId: Int // ushort actually
}
internal object NullPacketId : PacketId {
override val commandId: Int get() = error("uninitialized")
override val commandName: String get() = error("uninitialized")
override val subCommandId: Int get() = error("uninitialized")
}
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