Commit 39204730 authored by Him188's avatar Him188

Fix StackOverflowError

parent f4024518
...@@ -2,14 +2,12 @@ package net.mamoe.mirai.network ...@@ -2,14 +2,12 @@ package net.mamoe.mirai.network
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.io.core.use import kotlinx.io.core.use
import kotlinx.io.streams.inputStream import kotlinx.io.streams.inputStream
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.message.Image import net.mamoe.mirai.message.Image
import net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter
import net.mamoe.mirai.network.protocol.tim.packet.SessionKey import net.mamoe.mirai.network.protocol.tim.packet.SessionKey
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import java.io.InputStream import java.io.InputStream
...@@ -21,8 +19,9 @@ import java.io.InputStream ...@@ -21,8 +19,9 @@ import java.io.InputStream
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
actual class BotSession internal actual constructor( actual class BotSession internal actual constructor(
bot: Bot bot: Bot,
) : BotSessionBase(bot) { sessionKey: SessionKey
) : BotSessionBase(bot, sessionKey) {
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream() suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
suspend inline fun Image.downloadAsBitmap(): Bitmap = withContext(Dispatchers.IO) { downloadAsStream().use { BitmapFactory.decodeStream(it) } } suspend inline fun Image.downloadAsBitmap(): Bitmap = withContext(Dispatchers.IO) { downloadAsStream().use { BitmapFactory.decodeStream(it) } }
......
...@@ -41,10 +41,11 @@ fun GroupId.toInternalId(): GroupInternalId {//求你别出错 ...@@ -41,10 +41,11 @@ fun GroupId.toInternalId(): GroupInternalId {//求你别出错
) )
} }
fun GroupInternalId.toId(): GroupId {//求你别出错 fun GroupInternalId.toId(): GroupId = with(value) {
//求你别出错
var left: UInt = this.toString().let { var left: UInt = this.toString().let {
if (it.length < 6) { if (it.length < 6) {
return GroupId(this.value) return GroupId(value)
} }
it.substring(0 until it.length - 6).toUInt() it.substring(0 until it.length - 6).toUInt()
} }
...@@ -96,6 +97,6 @@ fun GroupInternalId.toId(): GroupId {//求你别出错 ...@@ -96,6 +97,6 @@ fun GroupInternalId.toId(): GroupId {//求你别出错
left = left.toString().substring(0 until 3).toUInt() left = left.toString().substring(0 until 3).toUInt()
((left - 349u).toString() + right.toString()).toUInt() ((left - 349u).toString() + right.toString()).toUInt()
} }
else -> this.value else -> value
}) })
} }
\ No newline at end of file
...@@ -6,8 +6,10 @@ import kotlinx.coroutines.CoroutineScope ...@@ -6,8 +6,10 @@ import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.data.Profile import net.mamoe.mirai.contact.data.Profile
import net.mamoe.mirai.network.BotSession import net.mamoe.mirai.network.BotSession
import net.mamoe.mirai.network.protocol.tim.packet.action.AvatarLink
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark
import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
import net.mamoe.mirai.utils.MiraiExperimentalAPI
/** /**
* QQ 对象. * QQ 对象.
...@@ -22,6 +24,12 @@ import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList ...@@ -22,6 +24,12 @@ import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
* @author Him188moe * @author Him188moe
*/ */
interface QQ : Contact, CoroutineScope { interface QQ : Contact, CoroutineScope {
/**
* 请求头像下载链接
*/
// @MiraiExperimentalAPI
//suspend fun queryAvatar(): AvatarLink
/** /**
* 查询用户资料 * 查询用户资料
*/ */
......
...@@ -31,7 +31,7 @@ import kotlin.coroutines.coroutineContext ...@@ -31,7 +31,7 @@ import kotlin.coroutines.coroutineContext
* 构造 [BotSession] 的捷径 * 构造 [BotSession] 的捷径
*/ */
@Suppress("FunctionName", "NOTHING_TO_INLINE") @Suppress("FunctionName", "NOTHING_TO_INLINE")
internal inline fun TIMBotNetworkHandler.BotSession(): BotSession = BotSession(bot) internal inline fun TIMBotNetworkHandler.BotSession(sessionKey: SessionKey): BotSession = BotSession(bot, sessionKey)
/** /**
* 登录会话. 当登录完成后, 客户端会拿到 sessionKey. * 登录会话. 当登录完成后, 客户端会拿到 sessionKey.
...@@ -43,7 +43,8 @@ internal inline fun TIMBotNetworkHandler.BotSession(): BotSession = BotSession(b ...@@ -43,7 +43,8 @@ internal inline fun TIMBotNetworkHandler.BotSession(): BotSession = BotSession(b
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
expect class BotSession internal constructor( expect class BotSession internal constructor(
bot: Bot bot: Bot,
sessionKey: SessionKey
) : BotSessionBase ) : BotSessionBase
/** /**
...@@ -52,9 +53,9 @@ expect class BotSession internal constructor( ...@@ -52,9 +53,9 @@ expect class BotSession internal constructor(
@MiraiInternalAPI @MiraiInternalAPI
// cannot be internal because of `public BotSession` // cannot be internal because of `public BotSession`
abstract class BotSessionBase internal constructor( abstract class BotSessionBase internal constructor(
val bot: Bot val bot: Bot,
internal val sessionKey: SessionKey
) { ) {
internal val sessionKey: SessionKey get() = bot.sessionKey
val socket: DataPacketSocketAdapter get() = bot.network.socket val socket: DataPacketSocketAdapter get() = bot.network.socket
val NetworkScope: CoroutineScope get() = bot.network val NetworkScope: CoroutineScope get() = bot.network
......
...@@ -474,7 +474,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou ...@@ -474,7 +474,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
BotLoginSucceedEvent(bot).broadcast() BotLoginSucceedEvent(bot).broadcast()
session = BotSession() session = BotSession(sessionKey)
val configuration = currentBotConfiguration() val configuration = currentBotConfiguration()
heartbeatJob = this@TIMBotNetworkHandler.launch { heartbeatJob = this@TIMBotNetworkHandler.launch {
......
...@@ -79,6 +79,7 @@ internal enum class KnownPacketId(override inline val value: UShort, override in ...@@ -79,6 +79,7 @@ internal enum class KnownPacketId(override inline val value: UShort, override in
inline REQUEST_PROFILE_AVATAR(0x0031u, RequestProfileAvatarPacket), inline REQUEST_PROFILE_AVATAR(0x0031u, RequestProfileAvatarPacket),
inline REQUEST_PROFILE_DETAILS(0x003Cu, RequestProfileDetailsPacket), inline REQUEST_PROFILE_DETAILS(0x003Cu, RequestProfileDetailsPacket),
inline QUERY_NICKNAME(0x0126u, QueryNicknamePacket),
inline QUERY_PREVIOUS_NAME(0x01BCu, QueryPreviousNamePacket), inline QUERY_PREVIOUS_NAME(0x01BCu, QueryPreviousNamePacket),
......
package net.mamoe.mirai.network.protocol.tim.packet.action
// 0001
// 已确认 查好友列表的列表
// send
// 20 01 00 00 00 00 01 00 00
// receive
// 20 00 01 03 00 00 00 15 01 01 03
// 00 0C 01 02 [09] E4 BF A1 E7 94 A8 E5 8D A1
// 00 0F 02 03 [0C] E8 BD AF E4 BB B6 E6 B3 A8 E5 86 8C
// 00 09 03 04 [06] E6 BA 90 E7 A0 81
// 00 00
// 0134
// 这里有好友也有群(为 internal id) 97208217
// 不太确定. 可能是查好友与群列表??
// send
// 00 00 01 5B 5D EB 58 AD 00 00 03 E8 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
// receive
// 00 00 19 00 00 01 5D 5D EB 5D C6 00 00 00 00 01 00 00 00 19 00 54 E5 06 01 00 00 00 00 00 01 00 00 00 64 B2 1D 01 00 00 00 00 00 01 00 00 00 66 7C C5 01 00 00 00 00 00 01 00 00 01 60 31 EC 01 00 00 00 00 00 01 00 00 01 B3 E6 AC 01 00 00 00 00 00 01 00 00 02 45 16 DF 01 00 00 00 00 00 01 00 00 03 37 67 20 01 00 00 00 00 00 01 00 00 05 B0 F4 6F 01 00 00 00 00 00 01 00 00 0C D9 1F 45 01 00 00 00 00 00 01 00 00 0F 0D 35 E1 01 00 00 00 00 00 01 00 00 10 18 86 83 01 00 00 00 00 00 01 00 00 11 A9 8B F7 01 00 00 00 00 00 01 00 00 31 05 12 1C 01 00 00 00 00 00 01 00 00 37 99 77 D7 01 00 00 00 00 00 01 00 00 37 C8 4D C7 04 00 00 00 00 00 00 37 E9 68 46 01 00 00 00 00 00 01 00 00 37 E9 94 CF 01 00 00 00 00 00 01 00 00 3E 03 3F A2 01 00 00 00 00 00 01 00 00 50 BA 4A 8F 01 00 00 00 00 00 01 00 00 55 7A D6 86 01 00 00 00 00 00 01 00 00 6C 78 B1 E0 01 00 00 00 00 00 01 00 00 78 59 79 87 01 00 00 00 00 00 01 00 00 79 9B 1B 59 04 00 00 00 00 00 00 A6 81 A4 9D 01 00 00 00 00 00 01 00 00 A6 A0 EE EF 01 00 00 00 00 00 01 00 00 00 00
...@@ -2,7 +2,26 @@ ...@@ -2,7 +2,26 @@
package net.mamoe.mirai package net.mamoe.mirai
import kotlinx.io.core.buildPacket
import kotlinx.io.core.readBytes
import net.mamoe.mirai.contact.GroupInternalId
import net.mamoe.mirai.contact.toId
import net.mamoe.mirai.utils.io.toByteArray
import net.mamoe.mirai.utils.io.toUHexString
actual object MiraiEnvironment { actual object MiraiEnvironment {
@JvmStatic @JvmStatic
actual val platform: Platform get() = Platform.JVM actual val platform: Platform
get() = Platform.JVM
}
@ExperimentalUnsignedTypes
fun main() {
println(GroupInternalId(2793514141u).toId().value.toLong())
println(GroupInternalId(2040208217u).toId().value.toLong())
println(289942298u.toByteArray().toUHexString())
println(1040400290u.toByteArray().toUHexString())
println(buildPacket {
writeStringUtf8("信用卡")
}.readBytes().toUByteArray().toUHexString())
} }
\ No newline at end of file
package net.mamoe.mirai.network package net.mamoe.mirai.network
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.io.core.use import kotlinx.io.core.use
import kotlinx.io.streams.inputStream import kotlinx.io.streams.inputStream
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.message.Image import net.mamoe.mirai.message.Image
import net.mamoe.mirai.network.protocol.tim.handler.DataPacketSocketAdapter
import net.mamoe.mirai.network.protocol.tim.packet.SessionKey import net.mamoe.mirai.network.protocol.tim.packet.SessionKey
import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
...@@ -24,8 +22,9 @@ import javax.imageio.ImageIO ...@@ -24,8 +22,9 @@ import javax.imageio.ImageIO
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
@Suppress("unused") @Suppress("unused")
actual class BotSession internal actual constructor( actual class BotSession internal actual constructor(
bot: Bot bot: Bot,
) : BotSessionBase(bot) { sessionKey: SessionKey
) : BotSessionBase(bot, sessionKey) {
suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream() suspend inline fun Image.downloadAsStream(): InputStream = download().inputStream()
suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(IO) { downloadAsStream().use { ImageIO.read(it) } } suspend inline fun Image.downloadAsBufferedImage(): BufferedImage = withContext(IO) { downloadAsStream().use { ImageIO.read(it) } }
......
...@@ -134,27 +134,29 @@ suspend fun main() { ...@@ -134,27 +134,29 @@ suspend fun main() {
println("Ready perfectly") println("Ready perfectly")
} }
suspend fun decryptRecordedPackets(filename: String) { suspend fun decryptRecordedPackets(filename: String?) {
File(filename).toRecorder() (if (filename == null) File(".").listFiles()?.maxBy { it.lastModified() }!!
.list.forEach { else File(filename)).toRecorder().also {
println("total count = " + it.list.size)
println()
}.list.forEach {
if (it.isSend) { if (it.isSend) {
try { try {
dataSent(it.data) dataSent(it.data)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() //e.printStackTrace()
} }
} else { } else {
try { try {
dataReceived(it.data) dataReceived(it.data)
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() // e.printStackTrace()
} }
} }
} }
} }
decryptRecordedPackets("GMTDate(seconds=3, minutes=46, hours=7, dayOfWeek=SATURDAY, dayOfMonth=7, dayOfYear=341, month=DECEMBER, year=2019, timestamp=1575704763731).record") decryptRecordedPackets(null)
//startPacketListening() //startPacketListening()
} }
...@@ -180,13 +182,13 @@ internal object PacketDebugger { ...@@ -180,13 +182,13 @@ internal object PacketDebugger {
* 7. 运行完 `mov eax,dword ptr ss:[ebp+10]` * 7. 运行完 `mov eax,dword ptr ss:[ebp+10]`
* 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey` * 8. 查看内存, `eax` 到 `eax+10` 的 16 字节就是 `sessionKey`
*/ */
val sessionKey: SessionKey = SessionKey("98 4C 42 37 0F 87 BB A2 97 57 A1 77 A9 A9 74 37".hexToBytes()) val sessionKey: SessionKey = SessionKey("F3 4A 4E F4 79 C4 92 62 EF 0F D8 6E D3 AB E3 80".hexToBytes())
// TODO: 2019/12/7 无法访问 internal 是 kotlin bug, KT-34849 // TODO: 2019/12/7 无法访问 internal 是 kotlin bug, KT-34849
/** /**
* null 则不筛选 * null 则不筛选
*/ */
val qq: UInt? = null val qq: UInt? = 215555909u
/** /**
* 打开后则记录每一个包到文件. * 打开后则记录每一个包到文件.
*/ */
...@@ -229,7 +231,7 @@ internal object PacketDebugger { ...@@ -229,7 +231,7 @@ internal object PacketDebugger {
} }
.runCatching { .runCatching {
decode(id, sequenceId, DebugNetworkHandler) decode(id, sequenceId, DebugNetworkHandler)
}.getOrElse { it.printStackTrace(); null } }.getOrElse { /*it.printStackTrace();*/ null }
} }
} }
...@@ -237,7 +239,9 @@ internal object PacketDebugger { ...@@ -237,7 +239,9 @@ internal object PacketDebugger {
if (packet !is IgnoredEventPacket) { if (packet !is IgnoredEventPacket) {
println("--------------") println("--------------")
println("接收包id=$id, \nsequence=${sequenceId.toUHexString()}") println("接收包id=$id, \nsequence=${sequenceId.toUHexString()}")
println(" 解密body=${decodedBody.toUHexString()}") if (packet !is UnknownPacket) {
println(" 解密body=${decodedBody.toUHexString()}")
}
println(" 解析body=$packet") println(" 解析body=$packet")
} }
...@@ -390,7 +394,7 @@ internal object DebugNetworkHandler : BotNetworkHandler<DataPacketSocketAdapter> ...@@ -390,7 +394,7 @@ internal object DebugNetworkHandler : BotNetworkHandler<DataPacketSocketAdapter>
} }
override val bot: Bot = Bot(qq ?: 0u, "", coroutineContext) override val bot: Bot = Bot(qq ?: 0u, "", coroutineContext)
override val session = BotSession(bot) override val session = BotSession(bot, SessionKey(byteArrayOf()))
override suspend fun login(): LoginResult = LoginResult.SUCCESS override suspend fun login(): LoginResult = LoginResult.SUCCESS
......
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