From 5ae4296bd5f2f6e41acc888fe5c7a455799026fa Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Wed, 29 Jan 2020 20:12:47 +0800
Subject: [PATCH 1/2] Fix PlatformSocket on Android

---
 .../mamoe/mirai/utils/io/PlatformSocket.kt    | 30 ++++++++++++++-----
 .../mamoe/mirai/utils/io/PlatformSocket.kt    |  4 ++-
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
index 33a951938..b4fdd1340 100644
--- a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
+++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
@@ -1,10 +1,14 @@
 package net.mamoe.mirai.utils.io
 
+import io.ktor.network.selector.ActorSelectorManager
 import io.ktor.network.sockets.Socket
 import io.ktor.network.sockets.aSocket
 import io.ktor.network.sockets.openReadChannel
 import io.ktor.network.sockets.openWriteChannel
 import io.ktor.util.KtorExperimentalAPI
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.io.ByteReadChannel
+import kotlinx.coroutines.io.ByteWriteChannel
 import kotlinx.coroutines.io.readAvailable
 import kotlinx.io.core.ByteReadPacket
 import kotlinx.io.core.Closeable
@@ -17,24 +21,28 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
 @MiraiInternalAPI
 actual class PlatformSocket : Closeable {
     @UseExperimental(KtorExperimentalAPI::class)
-    lateinit var channel: Socket
+    lateinit var socket: Socket
 
     @UseExperimental(KtorExperimentalAPI::class)
     actual val isOpen: Boolean
-        get() = channel.socketContext.isActive
+        get() = socket.socketContext.isActive
 
-    override fun close() = channel.dispose()
+    override fun close() = socket.dispose()
 
     @PublishedApi
-    internal val writeChannel = channel.openWriteChannel(true)
+    internal lateinit var writeChannel: ByteWriteChannel
     @PublishedApi
-    internal val readChannel = channel.openReadChannel()
+    internal lateinit var readChannel: ByteReadChannel
 
     /**
      * @throws SendPacketInternalException
      */
     actual suspend inline fun send(packet: ByteReadPacket) {
-        writeChannel.writePacket(packet)
+        try {
+            writeChannel.writePacket(packet)
+        } catch (e: Exception) {
+            throw SendPacketInternalException(e)
+        }
     }
 
     /**
@@ -43,13 +51,19 @@ actual class PlatformSocket : Closeable {
     actual suspend inline fun read(): ByteReadPacket {
         // do not use readChannel.readRemaining() !!! this function never returns
         ByteArrayPool.useInstance { buffer ->
-            val count = readChannel.readAvailable(buffer)
+            val count = try {
+                readChannel.readAvailable(buffer)
+            } catch (e: Exception) {
+                throw ReadPacketInternalException(e)
+            }
             return buffer.toReadPacket(0, count)
         }
     }
 
     @UseExperimental(KtorExperimentalAPI::class)
     actual suspend fun connect(serverHost: String, serverPort: Int) {
-        channel = aSocket(io.ktor.network.selector.ActorSelectorManager(kotlinx.coroutines.Dispatchers.IO)).tcp().connect(serverHost, serverPort)
+        socket = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp().connect(serverHost, serverPort)
+        writeChannel = socket.openWriteChannel(true)
+        readChannel = socket.openReadChannel()
     }
 }
\ No newline at end of file
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
index bfa804929..b4fdd1340 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
@@ -1,10 +1,12 @@
 package net.mamoe.mirai.utils.io
 
+import io.ktor.network.selector.ActorSelectorManager
 import io.ktor.network.sockets.Socket
 import io.ktor.network.sockets.aSocket
 import io.ktor.network.sockets.openReadChannel
 import io.ktor.network.sockets.openWriteChannel
 import io.ktor.util.KtorExperimentalAPI
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.io.ByteReadChannel
 import kotlinx.coroutines.io.ByteWriteChannel
 import kotlinx.coroutines.io.readAvailable
@@ -60,7 +62,7 @@ actual class PlatformSocket : Closeable {
 
     @UseExperimental(KtorExperimentalAPI::class)
     actual suspend fun connect(serverHost: String, serverPort: Int) {
-        socket = aSocket(io.ktor.network.selector.ActorSelectorManager(kotlinx.coroutines.Dispatchers.IO)).tcp().connect(serverHost, serverPort)
+        socket = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp().connect(serverHost, serverPort)
         writeChannel = socket.openWriteChannel(true)
         readChannel = socket.openReadChannel()
     }

From 7d06b49839d90aff239419ec460e0430eb7d7de4 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Wed, 29 Jan 2020 20:16:10 +0800
Subject: [PATCH 2/2] Add C2cMessageSyncData

---
 .../mirai/qqandroid/network/QQAndroidClient.kt     | 10 ++++++++++
 .../network/protocol/packet/chat/data/MsgSvc.kt    |  2 +-
 .../packet/chat/receive/MessageSvc.PushNotify.kt   | 14 ++++++++++++--
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
index e5f29721d..baefa2f31 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
@@ -8,6 +8,7 @@ import net.mamoe.mirai.BotAccount
 import net.mamoe.mirai.RawAccountIdUse
 import net.mamoe.mirai.data.OnlineStatus
 import net.mamoe.mirai.qqandroid.QQAndroidBot
+import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
 import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketLogger
 import net.mamoe.mirai.qqandroid.network.protocol.packet.Tlv
 import net.mamoe.mirai.qqandroid.utils.*
@@ -107,6 +108,15 @@ internal open class QQAndroidClient(
      */
     val protocolVersion: Short = 8001
 
+    class C2cMessageSyncData {
+        var syncCookie = EMPTY_BYTE_ARRAY
+        var pubAccountCookie = EMPTY_BYTE_ARRAY
+        var syncFlag: Int = 2
+        var msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY
+    }
+
+    val c2cMessageSync = C2cMessageSyncData()
+
     /*
      * 以下登录使用
      */
diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/data/MsgSvc.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/data/MsgSvc.kt
index 6840ab328..885530d04 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/data/MsgSvc.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/data/MsgSvc.kt
@@ -21,7 +21,7 @@ class MsgSvc : ProtoBuf {
         @SerialId(5) val uinPairMsgs: List<MsgComm.UinPairMsg>? = null,
         @SerialId(6) val bindUin: Long = 0L,
         @SerialId(7) val msgRspType: Int = 0,
-        @SerialId(8) val pubaccountCookie: ByteArray = EMPTY_BYTE_ARRAY,
+        @SerialId(8) val pubAccountCookie: ByteArray = EMPTY_BYTE_ARRAY,
         @SerialId(9) val isPartialSync: Boolean = false,
         @SerialId(10) val msgCtrlBuf: ByteArray = EMPTY_BYTE_ARRAY
     ) : ProtoBuf
diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt
index aab5a6a3f..054ec73b3 100644
--- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt
+++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/receive/MessageSvc.PushNotify.kt
@@ -19,6 +19,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.data.RequestPushNo
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.data.RequestDataVersion2
 import net.mamoe.mirai.qqandroid.network.protocol.packet.login.data.RequestPacket
 import net.mamoe.mirai.qqandroid.utils.toMessageChain
+import net.mamoe.mirai.utils.cryptor.contentToString
 import net.mamoe.mirai.utils.firstValue
 import net.mamoe.mirai.utils.io.hexToBytes
 import net.mamoe.mirai.utils.io.toReadPacket
@@ -58,7 +59,11 @@ class MessageSvc {
                     latestRambleNumber = 20,
                     otherRambleNumber = 3,
                     onlineSyncFlag = 1,
-                    serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY
+                    serverBuf = from.serverBuf ?: EMPTY_BYTE_ARRAY,
+                    syncCookie = client.c2cMessageSync.syncCookie,
+                    syncFlag = client.c2cMessageSync.syncFlag,
+                    msgCtrlBuf = client.c2cMessageSync.msgCtrlBuf,
+                    pubaccountCookie = client.c2cMessageSync.pubAccountCookie
                 )
             )
         }
@@ -67,7 +72,12 @@ class MessageSvc {
             // 00 00 01 0F 08 00 12 00 1A 34 08 FF C1 C4 F1 05 10 FF C1 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 8A CA 91 D1 0C 48 9B A5 BD 9B 0A 58 DE 9D 99 F8 08 60 1D 68 FF C1 C4 F1 05 70 00 20 02 2A 9D 01 08 F3 C1 C4 F1 05 10 A2 FF 8C F0 03 18 01 22 8A 01 0A 2A 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 18 A6 01 20 0B 28 AE F9 01 30 F4 C1 C4 F1 05 38 A7 E3 D8 D4 84 80 80 80 01 B8 01 CD B5 01 12 08 08 01 10 00 18 00 20 00 1A 52 0A 50 0A 27 08 00 10 F4 C1 C4 F1 05 18 A7 E3 D8 D4 04 20 00 28 0C 30 00 38 86 01 40 22 4A 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 12 08 0A 06 0A 04 4E 4D 53 4C 12 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 12 04 4A 02 08 00 30 01 2A 15 08 97 A2 C1 F1 05 10 95 A6 F5 E5 0C 18 01 30 01 40 01 48 81 01 2A 10 08 D3 F7 B5 F1 05 10 DD F1 92 B7 07 18 01 30 01 38 00 42 00 48 00
             discardExact(4)
             val resp = readRemainingAsProtoBuf(MsgSvc.PbGetMsgResp.serializer())
-            //println(resp.contentToString())
+
+            bot.client.c2cMessageSync.syncCookie = resp.syncCookie
+            bot.client.c2cMessageSync.pubAccountCookie = resp.pubAccountCookie
+            bot.client.c2cMessageSync.syncFlag = resp.syncFlag
+            bot.client.c2cMessageSync.msgCtrlBuf = resp.msgCtrlBuf
+            println(resp.contentToString())
 
             if (resp.uinPairMsgs == null) {
                 return MultiPacket(emptyList())