Commit d28b37bb authored by jiahua.liu's avatar jiahua.liu

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	mirai-core-qqandroid/src/jvmTest/kotlin/androidPacketTests/serverToClient.kt
parents 9516c308 21187a0a
...@@ -302,7 +302,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -302,7 +302,9 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
return return
} catch (e: Throwable) { } catch (e: Throwable) {
bot.logger.error("Caught unexpected exceptions", e) bot.logger.error("Caught unexpected exceptions", e)
continue dispose()
bot.tryReinitializeNetworkHandler(e)
return
} }
launch(context = PacketReceiveDispatcher + CoroutineName("Incoming Packet handler"), start = CoroutineStart.ATOMIC) { launch(context = PacketReceiveDispatcher + CoroutineName("Incoming Packet handler"), start = CoroutineStart.ATOMIC) {
processPacket(rawInput) processPacket(rawInput)
......
...@@ -25,6 +25,9 @@ import net.mamoe.mirai.utils.io.hexToBytes ...@@ -25,6 +25,9 @@ import net.mamoe.mirai.utils.io.hexToBytes
import net.mamoe.mirai.utils.io.toReadPacket import net.mamoe.mirai.utils.io.toReadPacket
class MessageSvc { class MessageSvc {
/**
* 告知要刷新消息
*/
internal object PushNotify : PacketFactory<RequestPushNotify>("MessageSvc.PushNotify") { internal object PushNotify : PacketFactory<RequestPushNotify>("MessageSvc.PushNotify") {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): RequestPushNotify {
discardExact(8) discardExact(8)
...@@ -42,13 +45,18 @@ class MessageSvc { ...@@ -42,13 +45,18 @@ class MessageSvc {
} }
} }
/**
* 进行刷新消息
*/
internal object PbGetMsg : PacketFactory<MultiPacket<FriendMessage>>("MessageSvc.PbGetMsg") { internal object PbGetMsg : PacketFactory<MultiPacket<FriendMessage>>("MessageSvc.PbGetMsg") {
val EXTRA_DATA = "08 00 12 33 6D 6F 64 65 6C 3A 78 69 61 6F 6D 69 20 36 3B 6F 73 3A 32 32 3B 76 65 72 73 69 6F 6E 3A 76 32 6D 61 6E 3A 78 69 61 6F 6D 69 73 79 73 3A 4C 4D 59 34 38 5A 18 E4 E1 A4 FF FE 2D 20 E9 E1 A4 FF FE 2D 28 A8 E1 A4 FF FE 2D 30 99 E1 A4 FF FE 2D".hexToBytes()
operator fun invoke( operator fun invoke(
client: QQAndroidClient, client: QQAndroidClient,
from: RequestPushNotify from: RequestPushNotify
): OutgoingPacket = buildOutgoingUniPacket( ): OutgoingPacket = buildOutgoingUniPacket(
client, client,
extraData = "08 00 12 33 6D 6F 64 65 6C 3A 78 69 61 6F 6D 69 20 36 3B 6F 73 3A 32 32 3B 76 65 72 73 69 6F 6E 3A 76 32 6D 61 6E 3A 78 69 61 6F 6D 69 73 79 73 3A 4C 4D 59 34 38 5A 18 E4 E1 A4 FF FE 2D 20 E9 E1 A4 FF FE 2D 28 A8 E1 A4 FF FE 2D 30 99 E1 A4 FF FE 2D".hexToBytes().toReadPacket() extraData = EXTRA_DATA.toReadPacket()
) { ) {
writeProtoBuf( writeProtoBuf(
MsgSvc.PbGetMsgReq.serializer(), MsgSvc.PbGetMsgReq.serializer(),
......
...@@ -14,7 +14,11 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.ImMsgBody ...@@ -14,7 +14,11 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.ImMsgBody
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.MsgOnlinePush
import net.mamoe.mirai.qqandroid.utils.toMessageChain import net.mamoe.mirai.qqandroid.utils.toMessageChain
internal class OnlinePush { internal class OnlinePush {
/**
* 接受群消息
*/
internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") { internal object PbPushGroupMsg : PacketFactory<GroupMessage>("OnlinePush.PbPushGroupMsg") {
@UseExperimental(ExperimentalStdlibApi::class) @UseExperimental(ExperimentalStdlibApi::class)
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): GroupMessage {
......
...@@ -274,12 +274,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -274,12 +274,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
println("type=$type") println("type=$type")
discardExact(2) discardExact(2)
val tlvMap: Map<Int, ByteArray> = this.readTLVMap() val tlvMap: TlvMap = this.readTLVMap()
return when (type.toInt()) { return when (type.toInt()) {
0 -> onLoginSuccess(tlvMap, bot) 0 -> onLoginSuccess(tlvMap, bot)
1, 15 -> onErrorMessage(tlvMap) 1, 15 -> onErrorMessage(tlvMap)
2 -> onSolveLoginCaptcha(tlvMap, bot) 2 -> onSolveLoginCaptcha(tlvMap, bot)
-96 -> onUnsafeDeviceLogin(tlvMap, bot) -96 -> onUnsafeDeviceLogin(tlvMap)
-52 -> onSMSVerifyNeeded(tlvMap, bot) -52 -> onSMSVerifyNeeded(tlvMap, bot)
else -> error("unknown login result type: $type") else -> error("unknown login result type: $type")
} }
...@@ -287,18 +287,18 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -287,18 +287,18 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
private fun onSMSVerifyNeeded( private fun onSMSVerifyNeeded(
tlvMap: Map<Int, ByteArray>, tlvMap: TlvMap,
bot: QQAndroidBot bot: QQAndroidBot
): LoginPacketResponse.SMSVerifyCodeNeeded { ): LoginPacketResponse.SMSVerifyCodeNeeded {
bot.client.t104 = tlvMap[0x104]!! bot.client.t104 = tlvMap.getOrFail(0x104)
return LoginPacketResponse.SMSVerifyCodeNeeded(tlvMap[0x174] ?: EMPTY_BYTE_ARRAY, tlvMap[0x402]!!) return LoginPacketResponse.SMSVerifyCodeNeeded(tlvMap[0x174] ?: EMPTY_BYTE_ARRAY, tlvMap.getOrFail(0x402))
} }
private fun onUnsafeDeviceLogin(tlvMap: Map<Int, ByteArray>, bot: QQAndroidBot): LoginPacketResponse.UnsafeLogin { private fun onUnsafeDeviceLogin(tlvMap: TlvMap): LoginPacketResponse.UnsafeLogin {
return LoginPacketResponse.UnsafeLogin(tlvMap[0x204]!!.toReadPacket().readRemainingBytes().encodeToString()) return LoginPacketResponse.UnsafeLogin(tlvMap.getOrFail(0x204).toReadPacket().readRemainingBytes().encodeToString())
} }
private fun onErrorMessage(tlvMap: Map<Int, ByteArray>): LoginPacketResponse.Error { private fun onErrorMessage(tlvMap: TlvMap): LoginPacketResponse.Error {
return tlvMap[0x146]?.toReadPacket()?.run { return tlvMap[0x146]?.toReadPacket()?.run {
readShort() // ver readShort() // ver
readShort() // code readShort() // code
...@@ -313,8 +313,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -313,8 +313,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
@InternalAPI @InternalAPI
@UseExperimental(MiraiDebugAPI::class) @UseExperimental(MiraiDebugAPI::class)
private fun onSolveLoginCaptcha(tlvMap: Map<Int, ByteArray>, bot: QQAndroidBot): LoginPacketResponse. Captcha { private fun onSolveLoginCaptcha(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse. Captcha {
val client = bot.client
// val ret = tlvMap[0x104]?.let { println(it.toUHexString()) } // val ret = tlvMap[0x104]?.let { println(it.toUHexString()) }
println() println()
val question = tlvMap[0x165] ?: error("CAPTCHA QUESTION UNKNOWN") val question = tlvMap[0x165] ?: error("CAPTCHA QUESTION UNKNOWN")
...@@ -322,8 +321,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -322,8 +321,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
0x36 -> { 0x36 -> {
//图片验证 //图片验证
DebugLogger.debug("是一个图片验证码") DebugLogger.debug("是一个图片验证码")
bot.client.t104 = tlvMap[0x104]!! bot.client.t104 = tlvMap.getOrFail(0x104)
val imageData = tlvMap[0x105]!!.toReadPacket() val imageData = tlvMap.getOrFail(0x105).toReadPacket()
val signInfoLength = imageData.readShort() val signInfoLength = imageData.readShort()
imageData.discardExact(2)//image Length imageData.discardExact(2)//image Length
val sign = imageData.readBytes(signInfoLength.toInt()) val sign = imageData.readBytes(signInfoLength.toInt())
...@@ -332,15 +331,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -332,15 +331,12 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
sign = sign sign = sign
) )
} }
else -> { else -> error("UNKNOWN CAPTCHA QUESTION: $question")
error("UNKNOWN CAPTCHA QUESTION: $question")
}
} }
return TODO()
} }
@UseExperimental(MiraiDebugAPI::class) @UseExperimental(MiraiDebugAPI::class)
private fun onLoginSuccess(tlvMap: Map<Int, ByteArray>, bot: QQAndroidBot): LoginPacketResponse.Success { private fun onLoginSuccess(tlvMap: TlvMap, bot: QQAndroidBot): LoginPacketResponse.Success {
val client = bot.client val client = bot.client
println("TLV KEYS: " + tlvMap.keys.joinToString { it.contentToString() }) println("TLV KEYS: " + tlvMap.keys.joinToString { it.contentToString() })
...@@ -544,7 +540,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -544,7 +540,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
} }
private fun Map<Int, ByteArray>.getOrEmpty(key: Int): ByteArray { private fun TlvMap.getOrEmpty(key: Int): ByteArray {
return this[key] ?: byteArrayOf() return this[key] ?: byteArrayOf()
} }
...@@ -623,7 +619,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt ...@@ -623,7 +619,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>("wt
* 设置 [QQAndroidClient.uin] * 设置 [QQAndroidClient.uin]
*/ */
private fun QQAndroidClient.analysisTlv113(t113: ByteArray) = t113.read { private fun QQAndroidClient.analysisTlv113(t113: ByteArray) = t113.read {
val uin = readUInt().toLong() _uin = readUInt().toLong()
/* /*
// nothing to do // nothing to do
......
...@@ -5,6 +5,7 @@ package net.mamoe.mirai.utils.io ...@@ -5,6 +5,7 @@ package net.mamoe.mirai.utils.io
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.String import kotlinx.io.core.String
import kotlinx.io.core.use import kotlinx.io.core.use
import net.mamoe.mirai.utils.checkOffsetAndLength
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
...@@ -16,6 +17,10 @@ import kotlin.jvm.JvmSynthetic ...@@ -16,6 +17,10 @@ import kotlin.jvm.JvmSynthetic
@Suppress("DuplicatedCode") // false positive. foreach is not common to UByteArray and ByteArray @Suppress("DuplicatedCode") // false positive. foreach is not common to UByteArray and ByteArray
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
fun List<Byte>.toUHexString(separator: String = " ", offset: Int = 0, length: Int = this.size - offset): String { fun List<Byte>.toUHexString(separator: String = " ", offset: Int = 0, length: Int = this.size - offset): String {
require(offset >= 0) { "offset shouldn't be negative: $offset" }
require(length >= 0) { "length shouldn't be negative: $length" }
require(offset + length <= this.size) { "offset ($offset) + length ($length) > array.size (${this.size})" }
if (length == 0) { if (length == 0) {
return "" return ""
} }
...@@ -36,6 +41,7 @@ fun List<Byte>.toUHexString(separator: String = " ", offset: Int = 0, length: In ...@@ -36,6 +41,7 @@ fun List<Byte>.toUHexString(separator: String = " ", offset: Int = 0, length: In
@Suppress("DuplicatedCode") // false positive. foreach is not common to UByteArray and ByteArray @Suppress("DuplicatedCode") // false positive. foreach is not common to UByteArray and ByteArray
@UseExperimental(ExperimentalUnsignedTypes::class) @UseExperimental(ExperimentalUnsignedTypes::class)
fun ByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: Int = this.size - offset): String { fun ByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: Int = this.size - offset): String {
this.checkOffsetAndLength(offset, length)
if (length == 0) { if (length == 0) {
return "" return ""
} }
...@@ -72,7 +78,8 @@ fun UByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: In ...@@ -72,7 +78,8 @@ fun UByteArray.toUHexString(separator: String = " ", offset: Int = 0, length: In
} }
} }
fun ByteArray.encodeToString(): String = String(this) @Suppress("NOTHING_TO_INLINE")
inline fun ByteArray.encodeToString(): String = String(this)
fun ByteArray.toReadPacket(offset: Int = 0, length: Int = this.size) = ByteReadPacket(this, offset = offset, length = length) fun ByteArray.toReadPacket(offset: Int = 0, length: Int = this.size) = ByteReadPacket(this, offset = offset, length = length)
......
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