Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
48850d73
Commit
48850d73
authored
Jan 06, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Pass compilation
parent
e4312074
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
217 additions
and
113 deletions
+217
-113
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/event/PacketReceivedEvent.kt
...in/net/mamoe/mirai/qqandroid/event/PacketReceivedEvent.kt
+10
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+54
-38
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt
...qandroid/network/protocol/packet/OutgoingPacketAndroid.kt
+27
-24
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+102
-6
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt
...ai/qqandroid/network/protocol/packet/login/LoginPacket.kt
+15
-18
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/ECDH.kt
...commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/ECDH.kt
+0
-22
mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/handler/DataPacketSocketAdapter.kt
...oe.mirai.timpc/network/handler/DataPacketSocketAdapter.kt
+2
-0
mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/packet/login/PasswordSubmission.kt
...oe.mirai.timpc/network/packet/login/PasswordSubmission.kt
+2
-2
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt
...dMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt
...c/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt
+3
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
...c/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
+1
-1
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/event/PacketReceivedEvent.kt
0 → 100644
View file @
48850d73
package
net.mamoe.mirai.qqandroid.event
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.event.Cancellable
import
net.mamoe.mirai.event.Event
/**
* 接收到数据包
*/
class
PacketReceivedEvent
(
val
packet
:
Packet
)
:
Event
(),
Cancellable
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
48850d73
package
net.mamoe.mirai.qqandroid.network
package
net.mamoe.mirai.qqandroid.network
import
kotlinx.coroutines.*
import
kotlinx.coroutines.*
import
kotlinx.io.core.*
import
kotlinx.io.core.use
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.event.PacketReceivedEvent
import
net.mamoe.mirai.qqandroid.network.protocol.packet.KnownPacketFactories
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import
net.mamoe.mirai.utils.LockFreeLinkedList
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.ClosedChannelException
import
net.mamoe.mirai.utils.io.PlatformDatagramChannel
import
net.mamoe.mirai.utils.io.ReadPacketInternalException
import
net.mamoe.mirai.utils.io.debugPrint
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
@UseExperimental
(
MiraiInternalAPI
::
class
)
internal
class
QQAndroidBotNetworkHandler
(
override
val
bot
:
QQAndroidBot
)
:
BotNetworkHandler
()
{
internal
class
QQAndroidBotNetworkHandler
(
override
val
bot
:
QQAndroidBot
)
:
BotNetworkHandler
()
{
override
val
supervisor
:
CompletableJob
=
SupervisorJob
(
bot
.
coroutineContext
[
Job
])
override
val
supervisor
:
CompletableJob
=
SupervisorJob
(
bot
.
coroutineContext
[
Job
])
private
val
channel
:
PlatformDatagramChannel
=
PlatformDatagramChannel
(
"wtlogin.qq.com"
,
8000
)
private
val
channel
:
PlatformDatagramChannel
=
PlatformDatagramChannel
(
"wtlogin.qq.com"
,
8000
)
override
suspend
fun
login
()
{
override
suspend
fun
login
()
{
launch
{
processReceive
()
}
launch
(
CoroutineName
(
"Incoming Packet Receiver"
))
{
processReceive
()
}
val
buffer
=
IoBuffer
.
Pool
.
borrow
()
LoginPacket
(
bot
.
client
).
sendAndExpect
<
LoginPacket
.
LoginPacketResponse
>()
buffer
.
writePacket
(
LoginPacket
(
bot
.
client
).
delegate
)
val
shouldBeSent
=
buffer
.
readRemaining
check
(
channel
.
send
(
buffer
)
==
shouldBeSent
)
{
"Buffer is not entirely sent. "
+
"Required sent length=$shouldBeSent, but after channel.send, "
+
"buffer remains ${buffer.readBytes().toUHexString()}"
}
buffer
.
release
(
IoBuffer
.
Pool
)
println
(
"Login sent"
)
println
(
"Login sent"
)
}
}
private
suspend
fun
processReceive
()
{
private
suspend
inline
fun
processReceive
()
{
while
(
channel
.
isOpen
)
{
while
(
channel
.
isOpen
)
{
val
buffer
=
IoBuffer
.
Pool
.
borrow
()
val
rawInput
=
try
{
channel
.
read
()
try
{
channel
.
read
(
buffer
)
// JVM: withContext(IO)
}
catch
(
e
:
ClosedChannelException
)
{
}
catch
(
e
:
ClosedChannelException
)
{
dispose
()
dispose
()
return
return
...
@@ -46,35 +47,50 @@ internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotN
...
@@ -46,35 +47,50 @@ internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotN
}
catch
(
e
:
Throwable
)
{
}
catch
(
e
:
Throwable
)
{
bot
.
logger
.
error
(
"Caught unexpected exceptions"
,
e
)
bot
.
logger
.
error
(
"Caught unexpected exceptions"
,
e
)
continue
continue
}
finally
{
if
(!
buffer
.
canRead
()
||
buffer
.
readRemaining
==
0
)
{
//size==0
//bot.logger.debug("processReceive: Buffer cannot be read")
buffer
.
release
(
IoBuffer
.
Pool
)
continue
}
// sometimes exceptions are thrown without this `if` clause
}
}
//buffer.resetForRead()
launch
(
CoroutineName
(
"Incoming Packet handler"
))
{
launch
(
CoroutineName
(
"handleServerPacket"
))
{
try
{
// `.use`: Ensure that the packet is consumed **totally**
rawInput
.
debugPrint
(
"Received"
)
// so that all the buffers are released
}
catch
(
e
:
Exception
)
{
ByteArrayPool
.
useInstance
{
bot
.
logger
.
error
(
e
)
val
length
=
buffer
.
readRemaining
-
1
buffer
.
readFully
(
it
,
0
,
length
)
buffer
.
resetForWrite
()
buffer
.
writeFully
(
it
,
0
,
length
)
}
}
ByteReadPacket
(
buffer
,
IoBuffer
.
Pool
).
use
{
input
->
}
try
{
input
.
debugPrint
(
"Received"
)
rawInput
.
use
{
}
catch
(
e
:
Exception
)
{
KnownPacketFactories
.
parseIncomingPacket
(
bot
,
rawInput
)
{
packet
:
Packet
,
packetId
:
PacketId
,
sequenceId
:
Int
->
bot
.
logger
.
error
(
e
)
if
(
PacketReceivedEvent
(
packet
).
broadcast
().
cancelled
)
{
return
}
packetListeners
.
forEach
{
listener
->
if
(
listener
.
filter
(
packetId
,
sequenceId
)
&&
packetListeners
.
remove
(
listener
))
{
listener
.
complete
(
packet
)
}
}
}
}
}
}
}
}
}
}
}
suspend
fun
<
E
:
Packet
>
OutgoingPacket
.
sendAndExpect
():
E
{
val
handler
=
PacketListener
(
packetId
=
packetId
,
sequenceId
=
sequenceId
)
packetListeners
.
addLast
(
handler
)
check
(
channel
.
send
(
delegate
))
{
packetListeners
.
remove
(
handler
);
"Cannot send packet"
}
@Suppress
(
"UNCHECKED_CAST"
)
return
handler
.
await
()
as
E
}
@PublishedApi
internal
val
packetListeners
=
LockFreeLinkedList
<
PacketListener
>()
@PublishedApi
internal
inner
class
PacketListener
(
val
packetId
:
PacketId
,
val
sequenceId
:
Int
)
:
CompletableDeferred
<
Packet
>
by
CompletableDeferred
(
supervisor
)
{
fun
filter
(
packetId
:
PacketId
,
sequenceId
:
Int
)
=
this
.
packetId
==
packetId
&&
this
.
sequenceId
==
sequenceId
}
override
suspend
fun
awaitDisconnection
()
{
override
suspend
fun
awaitDisconnection
()
{
while
(
true
)
{
while
(
true
)
{
delay
(
100
)
delay
(
100
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt
View file @
48850d73
...
@@ -7,9 +7,9 @@ import kotlinx.io.core.buildPacket
...
@@ -7,9 +7,9 @@ import kotlinx.io.core.buildPacket
import
kotlinx.io.core.writeFully
import
kotlinx.io.core.writeFully
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import
net.mamoe.mirai.qqandroid.utils.ECDH
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import
net.mamoe.mirai.utils.cryptor.DecrypterByteArray
import
net.mamoe.mirai.utils.cryptor.ECDH
import
net.mamoe.mirai.utils.cryptor.encryptAndWrite
import
net.mamoe.mirai.utils.cryptor.encryptAndWrite
import
net.mamoe.mirai.utils.cryptor.encryptBy
import
net.mamoe.mirai.utils.cryptor.encryptBy
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.io.*
...
@@ -21,7 +21,12 @@ import net.mamoe.mirai.utils.io.*
...
@@ -21,7 +21,12 @@ import net.mamoe.mirai.utils.io.*
internal
class
OutgoingPacket
constructor
(
internal
class
OutgoingPacket
constructor
(
name
:
String
?,
name
:
String
?,
val
packetId
:
PacketId
,
val
packetId
:
PacketId
,
val
sequenceId
:
Short
,
val
sequenceId
:
Int
,
// TODO: 2020/1/6 这个 sequenceId 设计有问题.
// 02 03 包里面的那个应该并不是 sequenceId.
// 它应该是固定的 0x001.
// 应该在这里填入 SSO 的 sequenceId.
// 同时考虑修改名称. 这可能不应该叫做 SSO. 它在全程都有
val
delegate
:
ByteReadPacket
val
delegate
:
ByteReadPacket
)
{
)
{
val
name
:
String
by
lazy
{
val
name
:
String
by
lazy
{
...
@@ -52,7 +57,7 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
...
@@ -52,7 +57,7 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
extraData
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
extraData
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
name
:
String
?
=
null
,
name
:
String
?
=
null
,
id
:
PacketId
=
this
.
id
,
id
:
PacketId
=
this
.
id
,
sequenceId
:
Shor
t
=
PacketFactory
.
atomicNextSequenceId
(),
sequenceId
:
In
t
=
PacketFactory
.
atomicNextSequenceId
(),
body
:
BytePacketBuilder
.()
->
Unit
body
:
BytePacketBuilder
.()
->
Unit
):
OutgoingPacket
=
OutgoingPacket
(
name
,
id
,
sequenceId
,
buildPacket
{
):
OutgoingPacket
=
OutgoingPacket
(
name
,
id
,
sequenceId
,
buildPacket
{
writeIntLVPacket
(
lengthOffset
=
{
it
+
4
})
{
writeIntLVPacket
(
lengthOffset
=
{
it
+
4
})
{
...
@@ -69,11 +74,6 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
...
@@ -69,11 +74,6 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
}
}
})
})
internal
class
CommandId
(
val
stringValue
:
String
,
val
id
:
Int
)
{
override
fun
toString
():
String
=
stringValue
}
private
val
BRP_STUB
=
ByteReadPacket
(
EMPTY_BYTE_ARRAY
)
private
val
BRP_STUB
=
ByteReadPacket
(
EMPTY_BYTE_ARRAY
)
/**
/**
...
@@ -85,7 +85,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
...
@@ -85,7 +85,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
internal
inline
fun
BytePacketBuilder
.
writeLoginSsoPacket
(
internal
inline
fun
BytePacketBuilder
.
writeLoginSsoPacket
(
client
:
QQAndroidClient
,
client
:
QQAndroidClient
,
subAppId
:
Long
,
subAppId
:
Long
,
commandId
:
Command
Id
,
packetId
:
Packet
Id
,
extraData
:
ByteReadPacket
=
BRP_STUB
,
extraData
:
ByteReadPacket
=
BRP_STUB
,
body
:
BytePacketBuilder
.(
ssoSequenceId
:
Int
)
->
Unit
body
:
BytePacketBuilder
.(
ssoSequenceId
:
Int
)
->
Unit
)
{
)
{
...
@@ -102,21 +102,25 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
...
@@ -102,21 +102,25 @@ internal inline fun BytePacketBuilder.writeLoginSsoPacket(
writeInt
((
extraData
.
remaining
+
4
).
toInt
())
writeInt
((
extraData
.
remaining
+
4
).
toInt
())
writePacket
(
extraData
)
writePacket
(
extraData
)
}
}
writeInt
(
commandId
.
stringValue
.
length
+
4
)
packetId
.
commandName
.
let
{
writeStringUtf8
(
commandId
.
stringValue
)
writeInt
(
it
.
length
+
4
)
writeStringUtf8
(
it
)
}
writeInt
(
4
+
4
)
writeInt
(
4
+
4
)
writeInt
(
45112203
)
// 02 B0 5B 8B
writeInt
(
45112203
)
// 02 B0 5B 8B
val
imei
=
client
.
device
.
imei
client
.
device
.
imei
.
let
{
writeInt
(
imei
.
length
+
4
)
writeInt
(
it
.
length
+
4
)
writeStringUtf8
(
imei
)
writeStringUtf8
(
it
)
}
writeInt
(
4
)
writeInt
(
4
)
val
ksid
=
client
.
device
.
ksid
client
.
device
.
ksid
.
let
{
writeShort
((
ksid
.
length
+
2
).
toShort
())
writeInt
(
it
.
length
+
4
)
writeStringUtf8
(
ksid
)
writeStringUtf8
(
it
)
}
writeInt
(
4
)
writeInt
(
4
)
}
}
...
@@ -226,10 +230,10 @@ internal interface EncryptMethodECDH : EncryptMethod {
...
@@ -226,10 +230,10 @@ internal interface EncryptMethodECDH : EncryptMethod {
override
fun
BytePacketBuilder
.
encryptAndWrite
(
body
:
ByteReadPacket
)
=
ecdh
.
run
{
override
fun
BytePacketBuilder
.
encryptAndWrite
(
body
:
ByteReadPacket
)
=
ecdh
.
run
{
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeFully
(
privateKey
)
writeFully
(
keyPair
.
privateKey
.
getEncoded
()
)
writeShort
(
258
)
// const
writeShort
(
258
)
// const
writeShortLVByteArray
(
publicKey
)
writeShortLVByteArray
(
keyPair
.
publicKey
.
getEncoded
().
drop
(
23
).
toByteArray
().
also
{
check
(
it
.
size
==
49
)
{
"Bad publicKey generated. Expected size=49, got${it.size}"
}
}
)
body
.
encryptBy
(
shareKey
)
{
encrypted
->
writeFully
(
encrypted
)
}
body
.
encryptBy
(
keyPair
.
shareKey
)
{
encrypted
->
writeFully
(
encrypted
)
}
}
}
}
}
...
@@ -256,8 +260,7 @@ internal interface EncryptMethodECDH : EncryptMethod {
...
@@ -256,8 +260,7 @@ internal interface EncryptMethodECDH : EncryptMethod {
internal
inline
fun
BytePacketBuilder
.
writeRequestPacket
(
internal
inline
fun
BytePacketBuilder
.
writeRequestPacket
(
client
:
QQAndroidClient
,
client
:
QQAndroidClient
,
encryptMethod
:
EncryptMethod
,
encryptMethod
:
EncryptMethod
,
commandId
:
CommandId
,
packetId
:
PacketId
,
sequenceId
:
Short
=
PacketFactory
.
atomicNextSequenceId
(),
bodyBlock
:
BytePacketBuilder
.()
->
Unit
bodyBlock
:
BytePacketBuilder
.()
->
Unit
)
{
)
{
val
body
=
encryptMethod
.
run
{
val
body
=
encryptMethod
.
run
{
...
@@ -268,8 +271,8 @@ internal inline fun BytePacketBuilder.writeRequestPacket(
...
@@ -268,8 +271,8 @@ internal inline fun BytePacketBuilder.writeRequestPacket(
writeByte
(
0
x02
)
// head
writeByte
(
0
x02
)
// head
writeShort
((
27
+
2
+
body
.
remaining
).
toShort
())
// orthodox algorithm
writeShort
((
27
+
2
+
body
.
remaining
).
toShort
())
// orthodox algorithm
writeShort
(
client
.
protocolVersion
)
writeShort
(
client
.
protocolVersion
)
writeShort
(
sequenceId
)
writeShort
(
1
)
writeShort
(
commandId
.
i
d
.
toShort
())
writeShort
(
packetId
.
commandI
d
.
toShort
())
writeQQ
(
client
.
account
.
id
)
writeQQ
(
client
.
account
.
id
)
writeByte
(
3
)
// originally const
writeByte
(
3
)
// originally const
writeByte
(
encryptMethod
.
id
.
toByte
())
writeByte
(
encryptMethod
.
id
.
toByte
())
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
48850d73
...
@@ -3,13 +3,21 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet
...
@@ -3,13 +3,21 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet
import
kotlinx.atomicfu.AtomicInt
import
kotlinx.atomicfu.AtomicInt
import
kotlinx.atomicfu.atomic
import
kotlinx.atomicfu.atomic
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.
network.BotNetworkHandler
import
net.mamoe.mirai.
qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.NullPacketId.commandName
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import
net.mamoe.mirai.utils.LockFreeLinkedList
import
net.mamoe.mirai.utils.cryptor.Decrypter
import
net.mamoe.mirai.utils.cryptor.Decrypter
import
net.mamoe.mirai.utils.cryptor.DecrypterType
import
net.mamoe.mirai.utils.cryptor.DecrypterType
import
net.mamoe.mirai.utils.cryptor.adjustToPublicKey
import
net.mamoe.mirai.utils.cryptor.decryptBy
import
net.mamoe.mirai.utils.io.*
import
kotlin.contracts.ExperimentalContracts
import
kotlin.contracts.contract
/**
/**
* 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包
* 一种数据包的处理工厂. 它可以解密解码服务器发来的这个包, 也可以编码加密要发送给服务器的这个包
...
@@ -32,21 +40,109 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
...
@@ -32,21 +40,109 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
/**
/**
* **解码**服务器的回复数据包
* **解码**服务器的回复数据包
*/
*/
abstract
suspend
fun
ByteReadPacket
.
decode
(
id
:
PacketId
,
sequenceId
:
Short
,
handler
:
BotNetworkHandler
):
TPacket
abstract
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
TPacket
companion
object
{
companion
object
{
private
val
sequenceId
:
AtomicInt
=
atomic
(
1
)
private
val
sequenceId
:
AtomicInt
=
atomic
(
1
)
fun
atomicNextSequenceId
():
Short
{
fun
atomicNextSequenceId
():
Int
{
TODO
(
"使用 SSO "
)
val
id
=
sequenceId
.
getAndAdd
(
1
)
val
id
=
sequenceId
.
getAndAdd
(
1
)
if
(
id
>
Short
.
MAX_VALUE
.
toInt
()
*
2
)
{
if
(
id
>
Short
.
MAX_VALUE
.
toInt
()
*
2
)
{
sequenceId
.
value
=
0
sequenceId
.
value
=
0
return
atomicNextSequenceId
()
return
atomicNextSequenceId
()
}
}
return
id
.
toShort
()
//
return id.toShort()
}
}
}
}
}
}
internal
class
KnownPacketFactories
:
LockFreeLinkedList
<
PacketFactory
<
*
,
*
>>()
{
private
val
DECRYPTER_16_ZERO
=
ByteArray
(
16
)
internal
typealias
PacketConsumer
=
(
packet
:
Packet
,
packetId
:
PacketId
,
ssoSequenceId
:
Int
)
->
Unit
internal
object
KnownPacketFactories
:
List
<
PacketFactory
<
*
,
*
>>
by
mutableListOf
()
{
fun
findPacketFactory
(
commandName
:
String
):
PacketFactory
<
*
,
*
>
=
this
.
first
{
it
.
id
.
commandName
==
commandName
}
fun
findPacketFactory
(
commandId
:
Int
):
PacketFactory
<
*
,
*
>
=
this
.
first
{
it
.
id
.
commandName
==
commandName
}
suspend
inline
fun
parseIncomingPacket
(
bot
:
QQAndroidBot
,
rawInput
:
ByteReadPacket
,
consumer
:
PacketConsumer
)
=
rawInput
.
debugPrintIfFail
(
"Incoming packet"
)
{
require
(
rawInput
.
remaining
<
Int
.
MAX_VALUE
)
{
"rawInput is too long"
}
val
expectedLength
=
readInt
()
-
4
check
(
rawInput
.
remaining
.
toInt
()
==
expectedLength
)
{
"Invalid packet length. Expected $expectedLength, got ${rawInput.remaining} Probably packets merged? "
}
// login
when
(
val
flag1
=
readInt
())
{
0
x0A
->
when
(
val
flag2
=
readByte
().
toInt
())
{
0
x02
->
{
val
flag3
=
readByte
().
toInt
()
check
(
flag3
==
0
)
{
"Illegal flag3. Expected 0, got $flag3"
}
discardExact
(
readInt
()
-
4
)
// uinAccount
parseLoginSsoPacket
(
bot
,
decryptBy
(
DECRYPTER_16_ZERO
),
consumer
)
}
else
->
error
(
"Illegal flag2. Expected 0x02, got $flag2"
)
}
else
->
error
(
"Illegal flag1. Expected 0x0A or 0x0B, got $flag1"
)
}
}
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
private
suspend
inline
fun
parseLoginSsoPacket
(
bot
:
QQAndroidBot
,
rawInput
:
ByteReadPacket
,
consumer
:
PacketConsumer
)
=
rawInput
.
debugPrintIfFail
(
"Login sso packet"
)
{
val
commandName
:
String
val
ssoSequenceId
:
Int
readIoBuffer
(
readInt
()
-
4
).
withUse
{
ssoSequenceId
=
readInt
()
check
(
readInt
()
==
0
)
val
loginExtraData
=
readIoBuffer
(
readInt
()
-
4
)
commandName
=
readString
(
readInt
()
-
4
)
val
unknown
=
readBytes
(
readInt
()
-
4
)
if
(
unknown
.
toInt
()
!=
0
x02B05B8B
)
DebugLogger
.
debug
(
"got new unknown: $unknown"
)
check
(
readInt
()
==
0
)
}
val
packetFactory
=
findPacketFactory
(
commandName
)
val
qq
:
Long
val
subCommandId
:
Int
readIoBuffer
(
readInt
()
-
4
).
withUse
{
check
(
readByte
().
toInt
()
==
2
)
discardExact
(
2
)
// 27 + 2 + body.size
discardExact
(
2
)
// const, =8001
readShort
()
// commandId
readShort
()
// innerSequenceId
qq
=
readInt
().
toLong
()
discardExact
(
1
)
// const = 0
val
packet
=
when
(
val
encryptionMethod
=
readByte
().
toInt
())
{
4
->
{
// peer public key, ECDH
packetFactory
.
run
{
bot
.
client
.
ecdh
.
calculateShareKeyByPeerPublicKey
(
readUShortLVByteArray
().
adjustToPublicKey
()).
read
{
decode
(
bot
)
}
}
}
else
->
error
(
"Illegal encryption method. expected 4, got $encryptionMethod"
)
}
consumer
(
packet
,
packetFactory
.
id
,
ssoSequenceId
)
}
}
}
@UseExperimental
(
ExperimentalContracts
::
class
)
internal
inline
fun
<
I
:
Closeable
,
R
>
I
.
withUse
(
block
:
I
.()
->
R
):
R
{
contract
{
callsInPlace
(
block
,
kotlin
.
contracts
.
InvocationKind
.
EXACTLY_ONCE
)
}
return
try
{
block
(
this
)
}
finally
{
close
()
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt
View file @
48850d73
...
@@ -5,7 +5,7 @@ import kotlinx.io.core.ByteReadPacket
...
@@ -5,7 +5,7 @@ import kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.buildPacket
import
kotlinx.io.core.buildPacket
import
kotlinx.io.core.readBytes
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.
network.BotNetworkHandler
import
net.mamoe.mirai.
qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.packet.*
import
net.mamoe.mirai.qqandroid.network.protocol.packet.*
import
net.mamoe.mirai.qqandroid.utils.GuidSource
import
net.mamoe.mirai.qqandroid.utils.GuidSource
...
@@ -21,7 +21,7 @@ class LoginPacketDecrypter(override val value: ByteArray) : DecrypterByteArray {
...
@@ -21,7 +21,7 @@ class LoginPacketDecrypter(override val value: ByteArray) : DecrypterByteArray {
internal
object
LoginPacket
:
PacketFactory
<
LoginPacket
.
LoginPacketResponse
,
LoginPacketDecrypter
>(
LoginPacketDecrypter
)
{
internal
object
LoginPacket
:
PacketFactory
<
LoginPacket
.
LoginPacketResponse
,
LoginPacketDecrypter
>(
LoginPacketDecrypter
)
{
init
{
init
{
this
.
_id
=
PacketId
(
CommandId
(
"wtlogin.login"
,
0
x0810
),
9
)
this
.
_id
=
PacketId
(
commandId
=
0
x0810
,
commandName
=
"wtlogin.login"
,
subCommandId
=
9
)
}
}
operator
fun
invoke
(
operator
fun
invoke
(
...
@@ -30,8 +30,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
...
@@ -30,8 +30,8 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
val
appId
=
16L
val
appId
=
16L
val
subAppId
=
537062845L
val
subAppId
=
537062845L
writeLoginSsoPacket
(
client
,
subAppId
,
_id
.
commandI
d
)
{
ssoSequenceId
->
writeLoginSsoPacket
(
client
,
subAppId
,
i
d
)
{
ssoSequenceId
->
writeRequestPacket
(
client
,
EncryptMethodECDH135
(
client
.
ecdh
),
_id
.
commandI
d
)
{
writeRequestPacket
(
client
,
EncryptMethodECDH135
(
client
.
ecdh
),
i
d
)
{
writeShort
(
9
)
// subCommand
writeShort
(
9
)
// subCommand
writeShort
(
LoginType
.
PASSWORD
.
value
.
toShort
())
writeShort
(
LoginType
.
PASSWORD
.
value
.
toShort
())
...
@@ -163,30 +163,27 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
...
@@ -163,30 +163,27 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
class
LoginPacketResponse
:
Packet
class
LoginPacketResponse
:
Packet
@ExperimentalUnsignedTypes
override
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
LoginPacketResponse
{
override
suspend
fun
ByteReadPacket
.
decode
(
id
:
PacketId
,
sequenceId
:
Short
,
handler
:
BotNetworkHandler
):
LoginPacketResponse
{
TODO
(
"not implemented"
)
TODO
()
}
}
}
}
@Suppress
(
"FunctionName"
)
@Suppress
(
"FunctionName"
)
internal
fun
PacketId
(
commandId
:
CommandId
,
subCommandId
:
Int
)
=
object
:
PacketId
{
internal
fun
PacketId
(
commandId
:
Int
,
commandName
:
String
,
subCommandId
:
Int
)
=
object
:
PacketId
{
override
val
commandId
:
CommandId
override
val
commandId
:
Int
get
()
=
commandId
get
()
=
commandId
override
val
commandName
:
String
get
()
=
commandName
override
val
subCommandId
:
Int
override
val
subCommandId
:
Int
get
()
=
subCommandId
get
()
=
subCommandId
}
}
internal
interface
PacketId
{
internal
interface
PacketId
{
val
commandId
:
CommandId
// ushort actually
val
commandId
:
Int
// ushort actually
val
commandName
:
String
val
subCommandId
:
Int
// ushort actually
val
subCommandId
:
Int
// ushort actually
}
}
internal
object
NullPacketId
:
PacketId
{
internal
object
NullPacketId
:
PacketId
{
override
val
commandId
:
CommandId
override
val
commandId
:
Int
get
()
=
error
(
"uninitialized"
)
get
()
=
error
(
"uninitialized"
)
override
val
commandName
:
String
get
()
=
error
(
"uninitialized"
)
override
val
subCommandId
:
Int
override
val
subCommandId
:
Int
get
()
=
error
(
"uninitialized"
)
get
()
=
error
(
"uninitialized"
)
}
}
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/ECDH.kt
deleted
100644 → 0
View file @
e4312074
package
net.mamoe.mirai.qqandroid.utils
/**
* From QQAndroid 8.2.0
* `oicq.wlogin_sdk.tools.EcdhCrypt`
*
* Constant to avoid calculations
*/
interface
ECDH
{
/*
object Default : ECDH {
override val publicKey: ByteArray = "020b03cf3d99541f29ffec281bebbd4ea211292ac1f53d7128".chunkedHexToBytes()
override val shareKey: ByteArray = "4da0f614fc9f29c2054c77048a6566d7".chunkedHexToBytes()
override val privateKey: ByteArray = ByteArray(16)
}*/
val
publicKey
:
ByteArray
val
shareKey
:
ByteArray
val
privateKey
:
ByteArray
}
\ No newline at end of file
mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/handler/DataPacketSocketAdapter.kt
View file @
48850d73
...
@@ -4,6 +4,7 @@ package net.mamoe.mirai.timpc.network.handler
...
@@ -4,6 +4,7 @@ package net.mamoe.mirai.timpc.network.handler
import
kotlinx.io.core.Closeable
import
kotlinx.io.core.Closeable
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.PlatformDatagramChannel
import
net.mamoe.mirai.utils.io.PlatformDatagramChannel
/**
/**
...
@@ -25,6 +26,7 @@ interface DataPacketSocketAdapter : Closeable {
...
@@ -25,6 +26,7 @@ interface DataPacketSocketAdapter : Closeable {
/**
/**
* UDP 通道
* UDP 通道
*/
*/
@MiraiInternalAPI
val
channel
:
PlatformDatagramChannel
val
channel
:
PlatformDatagramChannel
/**
/**
...
...
mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/packet/login/PasswordSubmission.kt
View file @
48850d73
...
@@ -26,7 +26,7 @@ internal inline class PrivateKey(override val value: ByteArray) : DecrypterByteA
...
@@ -26,7 +26,7 @@ internal inline class PrivateKey(override val value: ByteArray) : DecrypterByteA
}
}
internal
inline
class
SubmitPasswordResponseDecrypter
(
private
val
privateKey
:
PrivateKey
)
:
Decrypter
{
internal
inline
class
SubmitPasswordResponseDecrypter
(
private
val
privateKey
:
PrivateKey
)
:
Decrypter
{
override
fun
decrypt
(
input
:
ByteReadPacket
):
ByteReadPacket
{
override
fun
decrypt
(
input
:
ByteReadPacket
,
offset
:
Int
,
length
:
Int
):
ByteReadPacket
{
var
decrypted
=
ShareKey
.
decrypt
(
input
)
var
decrypted
=
ShareKey
.
decrypt
(
input
)
(
decrypted
.
remaining
).
let
{
(
decrypted
.
remaining
).
let
{
if
(
it
.
toInt
()
%
8
==
0
&&
it
>=
16
)
{
if
(
it
.
toInt
()
%
8
==
0
&&
it
>=
16
)
{
...
@@ -263,7 +263,7 @@ internal object SubmitPasswordPacket : PacketFactory<SubmitPasswordPacket.LoginR
...
@@ -263,7 +263,7 @@ internal object SubmitPasswordPacket : PacketFactory<SubmitPasswordPacket.LoginR
}
}
internal
inline
class
SessionResponseDecryptionKey
(
private
val
delegate
:
IoBuffer
)
:
Decrypter
{
internal
inline
class
SessionResponseDecryptionKey
(
private
val
delegate
:
IoBuffer
)
:
Decrypter
{
override
fun
decrypt
(
input
:
ByteReadPacket
):
ByteReadPacket
=
input
.
decryptBy
(
delegate
)
override
fun
decrypt
(
input
:
ByteReadPacket
,
offset
:
Int
,
length
:
Int
):
ByteReadPacket
=
input
.
decryptBy
(
delegate
)
override
fun
toString
():
String
=
"SessionResponseDecryptionKey"
override
fun
toString
():
String
=
"SessionResponseDecryptionKey"
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHAndroid.kt
View file @
48850d73
...
@@ -21,7 +21,7 @@ actual class ECDHKeyPair(
...
@@ -21,7 +21,7 @@ actual class ECDHKeyPair(
@Suppress
(
"FunctionName"
)
@Suppress
(
"FunctionName"
)
actual
fun
ECDH
()
=
ECDH
(
ECDH
.
generateKeyPair
())
actual
fun
ECDH
()
=
ECDH
(
ECDH
.
generateKeyPair
())
actual
class
ECDH
actual
constructor
(
val
keyPair
:
ECDHKeyPair
)
{
actual
class
ECDH
actual
constructor
(
actual
val
keyPair
:
ECDHKeyPair
)
{
actual
companion
object
{
actual
companion
object
{
actual
fun
generateKeyPair
():
ECDHKeyPair
{
actual
fun
generateKeyPair
():
ECDHKeyPair
{
return
ECDHKeyPair
(
KeyPairGenerator
.
getInstance
(
"ECDH"
).
genKeyPair
())
return
ECDHKeyPair
(
KeyPairGenerator
.
getInstance
(
"ECDH"
).
genKeyPair
())
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/ECDH.kt
View file @
48850d73
...
@@ -19,6 +19,8 @@ expect class ECDHKeyPair {
...
@@ -19,6 +19,8 @@ expect class ECDHKeyPair {
}
}
expect
class
ECDH
(
keyPair
:
ECDHKeyPair
)
{
expect
class
ECDH
(
keyPair
:
ECDHKeyPair
)
{
val
keyPair
:
ECDHKeyPair
fun
calculateShareKeyByPeerPublicKey
(
peerPublicKey
:
ECDHPublicKey
):
ByteArray
fun
calculateShareKeyByPeerPublicKey
(
peerPublicKey
:
ECDHPublicKey
):
ByteArray
companion
object
{
companion
object
{
...
@@ -47,5 +49,5 @@ fun ByteArray.adjustToPublicKey(): ECDHPublicKey {
...
@@ -47,5 +49,5 @@ fun ByteArray.adjustToPublicKey(): ECDHPublicKey {
else
(
byteArray_04
+
this
)
else
(
byteArray_04
+
this
)
}
else
this
}
else
this
return
ECDH
.
constructPublicKey
(
this
)
return
ECDH
.
constructPublicKey
(
key
)
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
View file @
48850d73
...
@@ -21,7 +21,7 @@ actual class ECDHKeyPair(
...
@@ -21,7 +21,7 @@ actual class ECDHKeyPair(
@Suppress
(
"FunctionName"
)
@Suppress
(
"FunctionName"
)
actual
fun
ECDH
()
=
ECDH
(
ECDH
.
generateKeyPair
())
actual
fun
ECDH
()
=
ECDH
(
ECDH
.
generateKeyPair
())
actual
class
ECDH
actual
constructor
(
val
keyPair
:
ECDHKeyPair
)
{
actual
class
ECDH
actual
constructor
(
actual
val
keyPair
:
ECDHKeyPair
)
{
actual
companion
object
{
actual
companion
object
{
actual
fun
generateKeyPair
():
ECDHKeyPair
{
actual
fun
generateKeyPair
():
ECDHKeyPair
{
return
ECDHKeyPair
(
KeyPairGenerator
.
getInstance
(
"ECDH"
).
genKeyPair
())
return
ECDHKeyPair
(
KeyPairGenerator
.
getInstance
(
"ECDH"
).
genKeyPair
())
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment