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
78ee01de
Commit
78ee01de
authored
Jan 07, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix bugs
parent
b6c15536
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
283 additions
and
120 deletions
+283
-120
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+22
-19
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+5
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt
...qandroid/network/protocol/packet/OutgoingPacketAndroid.kt
+63
-53
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+14
-25
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
.../net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
+16
-12
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt
...ai/qqandroid/network/protocol/packet/login/LoginPacket.kt
+5
-2
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
...oidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
+55
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt
+4
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt
...monMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt
+26
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
...c/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
+8
-2
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
...jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
+59
-0
mirai-core/src/jvmTest/kotlin/net/mamoe/mirai/utils/TypeConversionTest.kt
...vmTest/kotlin/net/mamoe/mirai/utils/TypeConversionTest.kt
+6
-1
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
78ee01de
...
@@ -14,7 +14,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
...
@@ -14,7 +14,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import
net.mamoe.mirai.utils.LockFreeLinkedList
import
net.mamoe.mirai.utils.LockFreeLinkedList
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.io.ClosedChannelException
import
net.mamoe.mirai.utils.io.ClosedChannelException
import
net.mamoe.mirai.utils.io.Platform
DatagramChannel
import
net.mamoe.mirai.utils.io.Platform
Socket
import
net.mamoe.mirai.utils.io.ReadPacketInternalException
import
net.mamoe.mirai.utils.io.ReadPacketInternalException
import
net.mamoe.mirai.utils.io.debugPrint
import
net.mamoe.mirai.utils.io.debugPrint
import
net.mamoe.mirai.utils.unsafeWeakRef
import
net.mamoe.mirai.utils.unsafeWeakRef
...
@@ -25,16 +25,18 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -25,16 +25,18 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
override
val
bot
:
QQAndroidBot
by
bot
.
unsafeWeakRef
()
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
lateinit
var
channel
:
PlatformSocket
override
suspend
fun
login
()
{
override
suspend
fun
login
()
{
channel
=
PlatformSocket
()
channel
.
connect
(
"113.96.13.208"
,
8080
)
launch
(
CoroutineName
(
"Incoming Packet Receiver"
))
{
processReceive
()
}
launch
(
CoroutineName
(
"Incoming Packet Receiver"
))
{
processReceive
()
}
println
(
"Sending login"
)
LoginPacket
.
SubCommand9
(
bot
.
client
).
sendAndExpect
<
LoginPacket
.
LoginPacketResponse
>()
LoginPacket
.
SubCommand9
(
bot
.
client
).
sendAndExpect
<
LoginPacket
.
LoginPacketResponse
>()
println
(
"Login sent"
)
}
}
private
suspend
inline
fun
processReceive
()
{
private
suspend
fun
processReceive
()
{
while
(
channel
.
isOpen
)
{
while
(
channel
.
isOpen
)
{
val
rawInput
=
try
{
val
rawInput
=
try
{
channel
.
read
()
channel
.
read
()
...
@@ -52,21 +54,19 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -52,21 +54,19 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
}
}
launch
(
CoroutineName
(
"Incoming Packet handler"
))
{
launch
(
CoroutineName
(
"Incoming Packet handler"
))
{
try
{
rawInput
.
debugPrint
(
"Received"
).
use
{
rawInput
.
debugPrint
(
"Received"
)
if
(
it
.
remaining
==
0L
)
{
}
catch
(
e
:
Exception
)
{
bot
.
logger
.
error
(
"Empty packet received. Consider if bad packet was sent."
)
bot
.
logger
.
error
(
e
)
return
@
launch
}
}
rawInput
.
use
{
KnownPacketFactories
.
parseIncomingPacket
(
bot
,
rawInput
)
{
packet
:
Packet
,
packetId
:
PacketId
,
sequenceId
:
Int
->
if
(
PacketReceivedEvent
(
packet
).
broadcast
().
cancelled
)
{
return
}
}
packetListeners
.
forEach
{
listener
->
KnownPacketFactories
.
parseIncomingPacket
(
bot
,
rawInput
)
{
packet
:
Packet
,
packetId
:
PacketId
,
sequenceId
:
Int
->
if
(
listener
.
filter
(
packetId
,
sequenceId
)
&&
packetListeners
.
remove
(
listener
))
{
if
(
PacketReceivedEvent
(
packet
).
broadcast
().
cancelled
)
{
listener
.
complete
(
packet
)
return
@
parseIncomingPacket
}
packetListeners
.
forEach
{
listener
->
if
(
listener
.
filter
(
packetId
,
sequenceId
)
&&
packetListeners
.
remove
(
listener
))
{
listener
.
complete
(
packet
)
}
}
}
}
}
}
}
...
@@ -77,7 +77,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
...
@@ -77,7 +77,10 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
suspend
fun
<
E
:
Packet
>
OutgoingPacket
.
sendAndExpect
():
E
{
suspend
fun
<
E
:
Packet
>
OutgoingPacket
.
sendAndExpect
():
E
{
val
handler
=
PacketListener
(
packetId
=
packetId
,
sequenceId
=
sequenceId
)
val
handler
=
PacketListener
(
packetId
=
packetId
,
sequenceId
=
sequenceId
)
packetListeners
.
addLast
(
handler
)
packetListeners
.
addLast
(
handler
)
check
(
channel
.
send
(
delegate
))
{
packetListeners
.
remove
(
handler
);
"Cannot send packet"
}
//println(delegate.readBytes().toUHexString())
println
(
"Sending length="
+
delegate
.
remaining
)
channel
.
send
(
delegate
)
//) { packetListeners.remove(handler); "Cannot send packet" }
println
(
"Packet sent"
)
@Suppress
(
"UNCHECKED_CAST"
)
@Suppress
(
"UNCHECKED_CAST"
)
return
handler
.
await
()
as
E
return
handler
.
await
()
as
E
}
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
78ee01de
...
@@ -4,7 +4,10 @@ import kotlinx.atomicfu.AtomicInt
...
@@ -4,7 +4,10 @@ import kotlinx.atomicfu.AtomicInt
import
kotlinx.atomicfu.atomic
import
kotlinx.atomicfu.atomic
import
kotlinx.io.core.toByteArray
import
kotlinx.io.core.toByteArray
import
net.mamoe.mirai.BotAccount
import
net.mamoe.mirai.BotAccount
import
net.mamoe.mirai.qqandroid.utils.*
import
net.mamoe.mirai.qqandroid.utils.Context
import
net.mamoe.mirai.qqandroid.utils.DeviceInfo
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.qqandroid.utils.SystemDeviceInfo
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.cryptor.ECDH
import
net.mamoe.mirai.utils.cryptor.ECDH
import
net.mamoe.mirai.utils.io.hexToBytes
import
net.mamoe.mirai.utils.io.hexToBytes
...
@@ -31,7 +34,7 @@ internal open class QQAndroidClient(
...
@@ -31,7 +34,7 @@ internal open class QQAndroidClient(
val
ecdh
:
ECDH
=
ECDH
(),
val
ecdh
:
ECDH
=
ECDH
(),
val
device
:
DeviceInfo
=
SystemDeviceInfo
(
context
)
val
device
:
DeviceInfo
=
SystemDeviceInfo
(
context
)
)
{
)
{
val
tgtgtKey
:
ByteArray
=
generateTgtgtKey
(
device
.
guid
)
val
tgtgtKey
:
ByteArray
=
ByteArray
(
16
)
//
generateTgtgtKey(device.guid)
var
miscBitMap
:
Int
=
184024956
// 也可能是 150470524 ?
var
miscBitMap
:
Int
=
184024956
// 也可能是 150470524 ?
var
mainSigMap
:
Int
=
16724722
var
mainSigMap
:
Int
=
16724722
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/OutgoingPacketAndroid.kt
View file @
78ee01de
...
@@ -11,7 +11,6 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
...
@@ -11,7 +11,6 @@ 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.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.io.*
import
net.mamoe.mirai.utils.io.*
/**
/**
...
@@ -47,6 +46,7 @@ private val EMPTY_BYTE_ARRAY = ByteArray(0)
...
@@ -47,6 +46,7 @@ private val EMPTY_BYTE_ARRAY = ByteArray(0)
*
*
* byte[] body encrypted by 16 zero
* byte[] body encrypted by 16 zero
*/
*/
@UseExperimental
(
MiraiInternalAPI
::
class
)
internal
inline
fun
PacketFactory
<*,
*>.
buildLoginOutgoingPacket
(
internal
inline
fun
PacketFactory
<*,
*>.
buildLoginOutgoingPacket
(
client
:
QQAndroidClient
,
client
:
QQAndroidClient
,
subAppId
:
Long
,
subAppId
:
Long
,
...
@@ -54,30 +54,33 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
...
@@ -54,30 +54,33 @@ internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
name
:
String
?
=
null
,
name
:
String
?
=
null
,
id
:
PacketId
=
this
.
id
,
id
:
PacketId
=
this
.
id
,
ssoExtraData
:
ByteReadPacket
=
BRP_STUB
,
ssoExtraData
:
ByteReadPacket
=
BRP_STUB
,
sequenceId
:
Int
=
PacketFactory
.
atomicNextSequenceId
(),
body
:
BytePacketBuilder
.(
sequenceId
:
Int
)
->
Unit
body
:
BytePacketBuilder
.(
sequenceId
:
Int
)
->
Unit
):
OutgoingPacket
=
OutgoingPacket
(
name
,
id
,
sequenceId
,
buildPacket
{
):
OutgoingPacket
{
writeIntLVPacket
(
lengthOffset
=
{
it
+
4
})
{
val
sequenceId
:
Int
=
client
.
nextSsoSequenceId
()
writeInt
(
0
x00_00_00_0A
)
writeByte
(
0
x02
)
return
OutgoingPacket
(
name
,
id
,
sequenceId
,
buildPacket
{
extraData
.
let
{
writeIntLVPacket
(
lengthOffset
=
{
it
+
4
})
{
writeInt
(
it
.
size
+
4
)
writeInt
(
0
x00_00_00_0A
)
writeFully
(
it
)
writeByte
(
0
x02
)
}
extraData
.
let
{
writeByte
(
0
x00
)
writeInt
(
it
.
size
+
4
)
writeFully
(
it
)
}
writeByte
(
0
x00
)
client
.
account
.
id
.
toString
().
let
{
client
.
account
.
id
.
toString
().
let
{
writeInt
(
it
.
length
+
4
)
writeInt
(
it
.
length
+
4
)
writeStringUtf8
(
it
)
writeStringUtf8
(
it
)
}
}
encryptAndWrite
(
KEY_16_ZEROS
)
{
encryptAndWrite
(
KEY_16_ZEROS
)
{
writeLoginSsoPacket
(
client
,
subAppId
,
id
,
ssoExtraData
,
sequenceId
)
{
writeLoginSsoPacket
(
client
,
subAppId
,
id
,
ssoExtraData
,
sequenceId
)
{
body
(
sequenceId
)
body
(
sequenceId
)
}
}
}
}
}
}
}
)
}
)
}
private
val
BRP_STUB
=
ByteReadPacket
(
EMPTY_BYTE_ARRAY
)
private
val
BRP_STUB
=
ByteReadPacket
(
EMPTY_BYTE_ARRAY
)
...
@@ -141,7 +144,7 @@ private inline fun BytePacketBuilder.writeLoginSsoPacket(
...
@@ -141,7 +144,7 @@ private inline fun BytePacketBuilder.writeLoginSsoPacket(
writeInt
(
4
)
writeInt
(
4
)
client
.
device
.
ksid
.
let
{
client
.
device
.
ksid
.
let
{
write
Int
(
it
.
length
+
4
)
write
Short
((
it
.
length
+
2
).
toShort
()
)
writeStringUtf8
(
it
)
writeStringUtf8
(
it
)
}
}
...
@@ -190,7 +193,7 @@ internal inline fun PacketFactory<*, *>.buildSessionOutgoingPacket(
...
@@ -190,7 +193,7 @@ internal inline fun PacketFactory<*, *>.buildSessionOutgoingPacket(
interface
EncryptMethod
{
interface
EncryptMethod
{
val
id
:
Int
val
id
:
Int
fun
BytePacketBuilder
.
encryptAndWrite
(
body
:
ByteReadPacket
)
fun
makeBody
(
body
:
BytePacketBuilder
.()
->
Unit
):
ByteReadPacket
}
}
internal
interface
EncryptMethodSessionKey
:
EncryptMethod
{
internal
interface
EncryptMethodSessionKey
:
EncryptMethod
{
...
@@ -208,14 +211,14 @@ internal interface EncryptMethodSessionKey : EncryptMethod {
...
@@ -208,14 +211,14 @@ internal interface EncryptMethodSessionKey : EncryptMethod {
* fully encrypted
* fully encrypted
* }
* }
*/
*/
override
fun
BytePacketBuilder
.
encryptAndWrite
(
body
:
ByteReadPacket
)
{
override
fun
makeBody
(
body
:
BytePacketBuilder
.()
->
Unit
):
ByteReadPacket
=
buildPacket
{
require
(
currentLoginState
==
2
||
currentLoginState
==
3
)
{
"currentLoginState must be either 2 or 3"
}
require
(
currentLoginState
==
2
||
currentLoginState
==
3
)
{
"currentLoginState must be either 2 or 3"
}
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeByte
(
if
(
currentLoginState
==
2
)
3
else
2
)
writeByte
(
if
(
currentLoginState
==
2
)
3
else
2
)
writeFully
(
sessionKey
)
writeFully
(
sessionKey
)
writeShort
(
258
)
// const
writeShort
(
258
)
// const
writeShort
(
0
)
// const, length of publicKey
writeShort
(
0
)
// const, length of publicKey
body
.
encryptBy
(
sessionKey
)
{
encrypted
->
writeFully
(
encrypted
)
}
encryptAndWrite
(
sessionKey
,
body
)
}
}
}
}
...
@@ -248,13 +251,22 @@ internal interface EncryptMethodECDH : EncryptMethod {
...
@@ -248,13 +251,22 @@ internal interface EncryptMethodECDH : EncryptMethod {
* byte[] [ECDH.publicKey]
* byte[] [ECDH.publicKey]
* byte[] encrypted `body()` by [ECDH.shareKey]
* byte[] encrypted `body()` by [ECDH.shareKey]
*/
*/
override
fun
BytePacketBuilder
.
encryptAndWrite
(
body
:
ByteReadPacket
)
=
ecdh
.
run
{
override
fun
makeBody
(
body
:
BytePacketBuilder
.()
->
Unit
):
ByteReadPacket
=
buildPacket
{
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeByte
(
1
)
// const
writeFully
(
keyPair
.
privateKey
.
getEncoded
(
))
writeFully
(
ByteArray
(
16
))
writeShort
(
258
)
// const
writeShort
(
258
)
// const
writeShortLVByteArray
(
keyPair
.
publicKey
.
getEncoded
().
drop
(
23
).
toByteArray
().
also
{
check
(
it
.
size
==
49
)
{
"Bad publicKey generated. Expected size=49, got${it.size}"
}
})
body
.
encryptBy
(
keyPair
.
shareKey
)
{
encrypted
->
writeFully
(
encrypted
)
}
writeShortLVByteArray
(
"04 CB 36 66 98 56 1E 93 6E 80 C1 57 E0 74 CA B1 3B 0B B6 8D DE B2 82 45 48 A1 B1 8D D4 FB 61 22 AF E1 2F E4 8C 52 66 D8 D7 26 9D 76 51 A8 EB 6F E7"
.
hexToBytes
())
/*writeShortLVByteArray(ecdh.keyPair.publicKey.getEncoded().drop(23).take(49).toByteArray().also {
it.toUHexString().debugPrint("PUBLIC KEY")
check(it[0].toInt() == 0x04) { "Bad publicKey generated. Expected first element=0x04, got${it[0]}" }
//check(ecdh.calculateShareKeyByPeerPublicKey(it.adjustToPublicKey()).contentEquals(ecdh.keyPair.shareKey)) { "PublicKey Validation failed" }
})*/
encryptAndWrite
(
"26 33 BA EC 86 EB 79 E6 BC E0 20 06 5E A9 56 6C"
.
hexToBytes
(),
body
)
//encryptAndWrite(ecdh.keyPair.shareKey, body)
}
}
}
}
...
@@ -278,36 +290,34 @@ internal interface EncryptMethodECDH : EncryptMethod {
...
@@ -278,36 +290,34 @@ internal interface EncryptMethodECDH : EncryptMethod {
* byte 3 // tail
* byte 3 // tail
*/
*/
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
,
MiraiInternalAPI
::
class
)
internal
inline
fun
BytePacketBuilder
.
writeOicqRequestPacket
(
internal
fun
BytePacketBuilder
.
writeOicqRequestPacket
(
client
:
QQAndroidClient
,
client
:
QQAndroidClient
,
encryptMethod
:
EncryptMethod
,
encryptMethod
:
EncryptMethod
,
packetId
:
PacketId
,
packetId
:
PacketId
,
bodyBlock
:
BytePacketBuilder
.()
->
Unit
bodyBlock
:
BytePacketBuilder
.()
->
Unit
)
{
)
{
val
body
=
encryptMethod
.
run
{
val
body
=
encryptMethod
.
makeBody
(
bodyBlock
)
buildPacket
{
encryptAndWrite
(
buildPacket
{
bodyBlock
()
})
}
// writeIntLVPacket(lengthOffset = { it + 4 }) {
}
// Head
writeIntLVPacket
(
lengthOffset
=
{
it
+
4
})
{
writeByte
(
0
x02
)
// head
// Head
writeShort
((
27
+
2
+
body
.
remaining
).
toShort
())
// orthodox algorithm
writeByte
(
0
x02
)
// head
writeShort
(
client
.
protocolVersion
)
writeShort
((
27
+
2
+
body
.
remaining
).
toShort
())
// orthodox algorithm
writeShort
(
packetId
.
commandId
.
toShort
())
writeShort
(
client
.
protocolVersion
)
writeShort
(
1
)
// const??
writeShort
(
1
)
// const??
writeQQ
(
client
.
account
.
id
)
writeShort
(
packetId
.
commandId
.
toShort
())
writeByte
(
3
)
// originally const
writeQQ
(
client
.
account
.
id
)
writeByte
(
encryptMethod
.
id
.
toByte
())
writeByte
(
3
)
// originally const
writeByte
(
0
)
// const8_always_0
writeByte
(
encryptMethod
.
id
.
toByte
())
writeInt
(
2
)
// originally const
writeByte
(
0
)
// const8_always_0
writeInt
(
client
.
appClientVersion
)
writeInt
(
2
)
// originally const
writeInt
(
0
)
// constp_always_0
writeInt
(
client
.
appClientVersion
)
writeInt
(
0
)
// constp_always_0
// Body
writePacket
(
body
)
// Body
writePacket
(
body
)
// Tail
writeByte
(
0
x03
)
// tail
// Tail
// }
writeByte
(
0
x03
)
// tail
}
}
}
/*
/*
00 00 01 64
00 00 01 64
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
78ee01de
package
net.mamoe.mirai.qqandroid.network.protocol.packet
package
net.mamoe.mirai.qqandroid.network.protocol.packet
import
kotlinx.atomicfu.AtomicInt
import
kotlinx.atomicfu.atomic
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.
Closeable
import
kotlinx.io.core.
IoBuffer
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.readBytes
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
...
@@ -41,25 +39,11 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
...
@@ -41,25 +39,11 @@ internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypt
* **解码**服务器的回复数据包
* **解码**服务器的回复数据包
*/
*/
abstract
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
TPacket
abstract
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
TPacket
companion
object
{
private
val
sequenceId
:
AtomicInt
=
atomic
(
1
)
fun
atomicNextSequenceId
():
Int
{
TODO
(
"使用 SSO "
)
val
id
=
sequenceId
.
getAndAdd
(
1
)
if
(
id
>
Short
.
MAX_VALUE
.
toInt
()
*
2
)
{
sequenceId
.
value
=
0
return
atomicNextSequenceId
()
}
// return id.toShort()
}
}
}
}
private
val
DECRYPTER_16_ZERO
=
ByteArray
(
16
)
private
val
DECRYPTER_16_ZERO
=
ByteArray
(
16
)
internal
typealias
PacketConsumer
=
(
packet
:
Packet
,
packetId
:
PacketId
,
ssoSequenceId
:
Int
)
->
Unit
internal
typealias
PacketConsumer
=
suspend
(
packet
:
Packet
,
packetId
:
PacketId
,
ssoSequenceId
:
Int
)
->
Unit
internal
object
KnownPacketFactories
:
List
<
PacketFactory
<
*
,
*
>>
by
mutableListOf
()
{
internal
object
KnownPacketFactories
:
List
<
PacketFactory
<
*
,
*
>>
by
mutableListOf
()
{
...
@@ -67,20 +51,25 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
...
@@ -67,20 +51,25 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
fun
findPacketFactory
(
commandId
:
Int
):
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
)
=
// do not inline. Exceptions thrown will not be reported correctly
suspend
fun
parseIncomingPacket
(
bot
:
QQAndroidBot
,
rawInput
:
ByteReadPacket
,
consumer
:
PacketConsumer
)
=
rawInput
.
debugPrintIfFail
(
"Incoming packet"
)
{
rawInput
.
debugPrintIfFail
(
"Incoming packet"
)
{
require
(
r
awInput
.
r
emaining
<
Int
.
MAX_VALUE
)
{
"rawInput is too long"
}
require
(
remaining
<
Int
.
MAX_VALUE
)
{
"rawInput is too long"
}
val
expectedLength
=
readInt
()
-
4
val
expectedLength
=
readInt
()
-
4
check
(
r
awInput
.
r
emaining
.
toInt
()
==
expectedLength
)
{
"Invalid packet length. Expected $expectedLength, got ${rawInput.remaining} Probably packets merged? "
}
check
(
remaining
.
toInt
()
==
expectedLength
)
{
"Invalid packet length. Expected $expectedLength, got ${rawInput.remaining} Probably packets merged? "
}
// login
// login
when
(
val
flag1
=
readInt
())
{
when
(
val
flag1
=
readInt
())
{
0
x0A
->
when
(
val
flag2
=
readByte
().
toInt
())
{
0
x0A
->
when
(
val
flag2
=
readByte
().
toInt
())
{
0
x02
->
{
0
x02
->
{
val
extraData
=
readIoBuffer
(
readInt
()
-
4
).
debugCopyUse
{
this
.
debugPrint
(
"Extra data"
)
}
val
flag3
=
readByte
().
toInt
()
val
flag3
=
readByte
().
toInt
()
check
(
flag3
==
0
)
{
"Illegal flag3. Expected 0, got $flag3"
}
check
(
flag3
==
0
)
{
"Illegal flag3. Expected 0, got $flag3"
}
discardExact
(
readInt
()
-
4
)
// uinAccount
bot
.
logger
.
verbose
(
readString
(
readInt
()
-
4
)
)
// uinAccount
//debugPrint("remaining")
parseLoginSsoPacket
(
bot
,
decryptBy
(
DECRYPTER_16_ZERO
),
consumer
)
parseLoginSsoPacket
(
bot
,
decryptBy
(
DECRYPTER_16_ZERO
),
consumer
)
}
}
else
->
error
(
"Illegal flag2. Expected 0x02, got $flag2"
)
else
->
error
(
"Illegal flag2. Expected 0x02, got $flag2"
)
...
@@ -90,7 +79,7 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
...
@@ -90,7 +79,7 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
}
}
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
private
suspend
inline
fun
parseLoginSsoPacket
(
bot
:
QQAndroidBot
,
rawInput
:
ByteReadPacket
,
consumer
:
PacketConsumer
)
=
private
suspend
fun
parseLoginSsoPacket
(
bot
:
QQAndroidBot
,
rawInput
:
ByteReadPacket
,
consumer
:
PacketConsumer
)
=
rawInput
.
debugPrintIfFail
(
"Login sso packet"
)
{
rawInput
.
debugPrintIfFail
(
"Login sso packet"
)
{
val
commandName
:
String
val
commandName
:
String
val
ssoSequenceId
:
Int
val
ssoSequenceId
:
Int
...
@@ -136,13 +125,13 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
...
@@ -136,13 +125,13 @@ internal object KnownPacketFactories : List<PacketFactory<*, *>> by mutableListO
}
}
@UseExperimental
(
ExperimentalContracts
::
class
)
@UseExperimental
(
ExperimentalContracts
::
class
)
internal
inline
fun
<
I
:
Closeable
,
R
>
I
.
withUse
(
block
:
I
.()
->
R
):
R
{
internal
inline
fun
<
I
:
IoBuffer
,
R
>
I
.
withUse
(
block
:
I
.()
->
R
):
R
{
contract
{
contract
{
callsInPlace
(
block
,
kotlin
.
contracts
.
InvocationKind
.
EXACTLY_ONCE
)
callsInPlace
(
block
,
kotlin
.
contracts
.
InvocationKind
.
EXACTLY_ONCE
)
}
}
return
try
{
return
try
{
block
(
this
)
block
(
this
)
}
finally
{
}
finally
{
close
(
)
this
.
release
(
IoBuffer
.
Pool
)
}
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/Tlv.kt
View file @
78ee01de
...
@@ -37,7 +37,7 @@ fun BytePacketBuilder.t1(uin: Long, ip: String) {
...
@@ -37,7 +37,7 @@ fun BytePacketBuilder.t1(uin: Long, ip: String) {
writeInt
(
Random
.
nextInt
())
writeInt
(
Random
.
nextInt
())
writeInt
(
uin
.
toInt
())
writeInt
(
uin
.
toInt
())
writeTime
()
writeTime
()
write
IP
(
ip
)
write
Fully
(
ByteArray
(
4
)
)
writeShort
(
0
)
writeShort
(
0
)
}
shouldEqualsTo
20
}
shouldEqualsTo
20
}
}
...
@@ -273,8 +273,8 @@ fun BytePacketBuilder.t109(
...
@@ -273,8 +273,8 @@ fun BytePacketBuilder.t109(
)
{
)
{
writeShort
(
0
x109
)
writeShort
(
0
x109
)
writeShortLVPacket
{
writeShortLVPacket
{
writeFully
(
androidId
)
writeFully
(
md5
(
androidId
)
)
}
}
shouldEqualsTo
16
}
}
fun
BytePacketBuilder
.
t52d
(
fun
BytePacketBuilder
.
t52d
(
...
@@ -283,6 +283,9 @@ fun BytePacketBuilder.t52d(
...
@@ -283,6 +283,9 @@ fun BytePacketBuilder.t52d(
writeShort
(
0
x52d
)
writeShort
(
0
x52d
)
writeShortLVPacket
{
writeShortLVPacket
{
writeFully
(
androidDevInfo
)
writeFully
(
androidDevInfo
)
// 0A 07 75 6E 6B 6E 6F 77 6E 12 7E 4C 69 6E 75 78 20 76 65 72 73 69 6F 6E 20 34 2E 39 2E 33 31 20 28 62 75 69 6C 64 40 42 75 69 6C 64 32 29 20 28 67 63 63 20 76 65 72 73 69 6F 6E 20 34 2E 39 20 32 30 31 35 30 31 32 33 20 28 70 72 65 72 65 6C 65 61 73 65 29 20 28 47 43 43 29 20 29 20 23 31 20 53 4D 50 20 50 52 45 45 4D 50 54 20 54 68 75 20 44 65 63 20 31 32 20 31 35 3A 33 30 3A 35 35 20 49 53 54 20 32 30 31 39 1A 03 52 45 4C 22 03 33 32 37 2A 41 4F 6E 65 50 6C 75 73 2F 4F 6E 65 50 6C 75 73 35 2F 4F 6E 65 50 6C 75 73 35 3A 37 2E 31 2E 31 2F 4E 4D 46 32 36 58 2F 31 30 31 37 31 36 31 37 3A 75 73 65 72 2F 72 65 6C 65 61 73 65 2D 6B 65 79 73 32 24 36 63 39 39 37 36 33 66 2D 66 62 34 32 2D 34 38 38 31 2D 62 37 32 65 2D 63 37 61 61 38 61 36 63 31 63 61 34 3A 10 65 38 63 37 30 35 34 64 30 32 66 33 36 33 64 30 42 0A 6E 6F 20 6D 65 73 73 61 67 65 4A 03 33 32 37
}
}
}
}
...
@@ -301,7 +304,6 @@ fun BytePacketBuilder.t124(
...
@@ -301,7 +304,6 @@ fun BytePacketBuilder.t124(
writeShort
(
networkType
.
value
.
toShort
())
writeShort
(
networkType
.
value
.
toShort
())
writeShortLVByteArrayLimitedLength
(
simInfo
,
16
)
writeShortLVByteArrayLimitedLength
(
simInfo
,
16
)
writeShortLVByteArrayLimitedLength
(
unknown
,
32
)
writeShortLVByteArrayLimitedLength
(
unknown
,
32
)
writeShort
(
0
)
writeShortLVByteArrayLimitedLength
(
apn
,
16
)
writeShortLVByteArrayLimitedLength
(
apn
,
16
)
}
}
}
}
...
@@ -385,7 +387,7 @@ fun BytePacketBuilder.t147(
...
@@ -385,7 +387,7 @@ fun BytePacketBuilder.t147(
)
{
)
{
writeShort
(
0
x147
)
writeShort
(
0
x147
)
writeShortLVPacket
{
writeShortLVPacket
{
write
Long
(
appId
)
write
Int
(
appId
.
toInt
()
)
writeShortLVByteArrayLimitedLength
(
apkVersionName
,
32
)
writeShortLVByteArrayLimitedLength
(
apkVersionName
,
32
)
writeShortLVByteArrayLimitedLength
(
apkSignatureMd5
,
32
)
writeShortLVByteArrayLimitedLength
(
apkSignatureMd5
,
32
)
}
}
...
@@ -516,16 +518,18 @@ fun BytePacketBuilder.t188(
...
@@ -516,16 +518,18 @@ fun BytePacketBuilder.t188(
writeShort
(
0
x188
)
writeShort
(
0
x188
)
writeShortLVPacket
{
writeShortLVPacket
{
writeFully
(
md5
(
androidId
))
writeFully
(
md5
(
androidId
))
}
}
shouldEqualsTo
16
}
}
fun
BytePacketBuilder
.
t194
(
fun
BytePacketBuilder
.
t194
(
imsiMd5
:
ByteArray
imsiMd5
:
ByteArray
)
{
)
{
imsiMd5
requireSize
16
writeShort
(
0
x194
)
writeShort
(
0
x194
)
writeShortLVPacket
{
writeShortLVPacket
{
writeFully
(
imsiMd5
)
writeFully
(
imsiMd5
)
}
}
shouldEqualsTo
16
}
}
fun
BytePacketBuilder
.
t191
(
fun
BytePacketBuilder
.
t191
(
...
@@ -572,7 +576,7 @@ fun BytePacketBuilder.t177(
...
@@ -572,7 +576,7 @@ fun BytePacketBuilder.t177(
writeByte
(
1
)
writeByte
(
1
)
writeInt
(
unknown1
.
toInt
())
writeInt
(
unknown1
.
toInt
())
writeShortLVString
(
unknown2
)
writeShortLVString
(
unknown2
)
}
}
shouldEqualsTo
0
x11
}
}
fun
BytePacketBuilder
.
t516
(
// 1302
fun
BytePacketBuilder
.
t516
(
// 1302
...
@@ -581,7 +585,7 @@ fun BytePacketBuilder.t516( // 1302
...
@@ -581,7 +585,7 @@ fun BytePacketBuilder.t516( // 1302
writeShort
(
0
x516
)
writeShort
(
0
x516
)
writeShortLVPacket
{
writeShortLVPacket
{
writeInt
(
sourceType
)
writeInt
(
sourceType
)
}
}
shouldEqualsTo
4
}
}
fun
BytePacketBuilder
.
t521
(
// 1313
fun
BytePacketBuilder
.
t521
(
// 1313
...
@@ -592,7 +596,7 @@ fun BytePacketBuilder.t521( // 1313
...
@@ -592,7 +596,7 @@ fun BytePacketBuilder.t521( // 1313
writeShortLVPacket
{
writeShortLVPacket
{
writeInt
(
productType
)
writeInt
(
productType
)
writeShort
(
unknown
)
writeShort
(
unknown
)
}
}
shouldEqualsTo
6
}
}
fun
BytePacketBuilder
.
t536
(
// 1334
fun
BytePacketBuilder
.
t536
(
// 1334
...
@@ -626,8 +630,8 @@ fun BytePacketBuilder.t318(
...
@@ -626,8 +630,8 @@ fun BytePacketBuilder.t318(
private
fun
Boolean
.
toByte
():
Byte
=
if
(
this
)
1
else
0
private
fun
Boolean
.
toByte
():
Byte
=
if
(
this
)
1
else
0
private
fun
Boolean
.
toInt
():
Int
=
if
(
this
)
1
else
0
private
fun
Boolean
.
toInt
():
Int
=
if
(
this
)
1
else
0
private
infix
fun
Int
.
shouldEqualsTo
(
int
:
Int
)
=
require
(
this
==
int
)
{
"Required $int, but found $this"
}
private
infix
fun
Int
.
shouldEqualsTo
(
int
:
Int
)
=
check
(
this
==
int
)
{
"Required $int, but found $this"
}
private
fun
ByteArray
.
requireSize
(
exactSize
:
Int
)
=
require
(
this
.
size
==
exactSize
)
{
"Required size $exactSize, but found ${this.size}"
}
private
infix
fun
ByteArray
.
requireSize
(
exactSize
:
Int
)
=
check
(
this
.
size
==
exactSize
)
{
"Required size $exactSize, but found ${this.size}"
}
fun
randomAndroidId
():
String
=
buildString
(
15
)
{
fun
randomAndroidId
():
String
=
buildString
(
15
)
{
repeat
(
15
)
{
append
(
Random
.
nextInt
(
10
))
}
repeat
(
15
)
{
append
(
Random
.
nextInt
(
10
))
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/LoginPacket.kt
View file @
78ee01de
...
@@ -31,9 +31,10 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
...
@@ -31,9 +31,10 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
operator
fun
invoke
(
operator
fun
invoke
(
client
:
QQAndroidClient
client
:
QQAndroidClient
):
OutgoingPacket
=
buildLoginOutgoingPacket
(
client
,
subAppId
)
{
sequenceId
->
):
OutgoingPacket
=
buildLoginOutgoingPacket
(
client
,
subAppId
)
{
sequenceId
->
writeOicqRequestPacket
(
client
,
EncryptMethodECDH
135
(
client
.
ecdh
),
id
)
{
writeOicqRequestPacket
(
client
,
EncryptMethodECDH
7
(
client
.
ecdh
),
id
)
{
writeShort
(
9
)
// subCommand
writeShort
(
9
)
// subCommand
writeShort
(
LoginType
.
PASSWORD
.
value
.
toShort
())
writeShort
(
0
x17
)
//writeShort(LoginType.PASSWORD.value.toShort())
t18
(
appId
,
client
.
appClientVersion
,
client
.
account
.
id
)
t18
(
appId
,
client
.
appClientVersion
,
client
.
account
.
id
)
t1
(
client
.
account
.
id
,
client
.
device
.
ipAddress
)
t1
(
client
.
account
.
id
,
client
.
device
.
ipAddress
)
...
@@ -91,6 +92,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
...
@@ -91,6 +92,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
tgtgtKey
=
client
.
tgtgtKey
tgtgtKey
=
client
.
tgtgtKey
)
)
//this.build().debugPrint("傻逼")
t145
(
client
.
device
.
guid
)
t145
(
client
.
device
.
guid
)
t147
(
appId
,
client
.
apkVersionName
,
client
.
apkSignatureMd5
)
t147
(
appId
,
client
.
apkVersionName
,
client
.
apkSignatureMd5
)
...
@@ -156,6 +158,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
...
@@ -156,6 +158,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
writeByte
(
0
)
// data count
writeByte
(
0
)
// data count
}.
readBytes
())
}.
readBytes
())
})
})
// this.build().debugPrint("傻逼")
// ignored t318 because not logging in by QR
// ignored t318 because not logging in by QR
}
}
...
...
mirai-core/src/androidMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
0 → 100644
View file @
78ee01de
package
net.mamoe.mirai.utils.io
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.io.readAvailable
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 多平台适配的 TCP Socket.
*/
@MiraiInternalAPI
actual
class
PlatformSocket
:
Closeable
{
@UseExperimental
(
KtorExperimentalAPI
::
class
)
lateinit
var
channel
:
Socket
@UseExperimental
(
KtorExperimentalAPI
::
class
)
actual
val
isOpen
:
Boolean
get
()
=
channel
.
socketContext
.
isActive
override
fun
close
()
=
channel
.
dispose
()
@PublishedApi
internal
val
writeChannel
=
channel
.
openWriteChannel
(
true
)
@PublishedApi
internal
val
readChannel
=
channel
.
openReadChannel
()
/**
* @throws SendPacketInternalException
*/
actual
suspend
inline
fun
send
(
packet
:
ByteReadPacket
)
{
writeChannel
.
writePacket
(
packet
)
}
/**
* @throws ReadPacketInternalException
*/
actual
suspend
inline
fun
read
():
ByteReadPacket
{
// do not use readChannel.readRemaining() !!! this function never returns
ByteArrayPool
.
useInstance
{
buffer
->
val
count
=
readChannel
.
readAvailable
(
buffer
)
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
)
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/TEA.kt
View file @
78ee01de
...
@@ -94,17 +94,17 @@ fun IoBuffer.decryptBy(key: ByteArray, offset: Int = 0, length: Int = readRemain
...
@@ -94,17 +94,17 @@ fun IoBuffer.decryptBy(key: ByteArray, offset: Int = 0, length: Int = readRemain
// region ByteReadPacket extension
// region ByteReadPacket extension
fun
ByteReadPacket
.
decryptBy
(
key
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
key
.
size
-
offset
):
ByteReadPacket
=
decryptAsByteArray
(
key
,
offset
,
length
)
{
data
->
ByteReadPacket
(
data
)
}
fun
ByteReadPacket
.
decryptBy
(
key
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
(
this
.
remaining
-
offset
).
toInt
()
):
ByteReadPacket
=
decryptAsByteArray
(
key
,
offset
,
length
)
{
data
->
ByteReadPacket
(
data
)
}
fun
ByteReadPacket
.
decryptBy
(
key
:
IoBuffer
,
offset
:
Int
=
0
,
length
:
Int
=
key
.
readRemaining
-
offset
):
ByteReadPacket
=
decryptAsByteArray
(
key
,
offset
,
length
)
{
data
->
ByteReadPacket
(
data
)
}
fun
ByteReadPacket
.
decryptBy
(
key
:
IoBuffer
,
offset
:
Int
=
0
,
length
:
Int
=
(
this
.
remaining
-
offset
).
toInt
()
):
ByteReadPacket
=
decryptAsByteArray
(
key
,
offset
,
length
)
{
data
->
ByteReadPacket
(
data
)
}
inline
fun
<
R
>
ByteReadPacket
.
decryptAsByteArray
(
key
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
key
.
size
-
offset
,
consumer
:
(
ByteArray
)
->
R
):
R
=
inline
fun
<
R
>
ByteReadPacket
.
decryptAsByteArray
(
key
:
ByteArray
,
offset
:
Int
=
0
,
length
:
Int
=
(
this
.
remaining
-
offset
).
toInt
()
,
consumer
:
(
ByteArray
)
->
R
):
R
=
ByteArrayPool
.
useInstance
{
ByteArrayPool
.
useInstance
{
readFully
(
it
,
offset
,
length
)
readFully
(
it
,
offset
,
length
)
consumer
(
it
.
decryptBy
(
key
,
length
))
consumer
(
it
.
decryptBy
(
key
,
length
))
}.
also
{
close
()
}
}.
also
{
close
()
}
inline
fun
<
R
>
ByteReadPacket
.
decryptAsByteArray
(
key
:
IoBuffer
,
offset
:
Int
=
0
,
length
:
Int
=
key
.
readRemaining
-
offset
,
consumer
:
(
ByteArray
)
->
R
):
R
=
inline
fun
<
R
>
ByteReadPacket
.
decryptAsByteArray
(
key
:
IoBuffer
,
offset
:
Int
=
0
,
length
:
Int
=
(
this
.
remaining
-
offset
).
toInt
()
,
consumer
:
(
ByteArray
)
->
R
):
R
=
ByteArrayPool
.
useInstance
{
ByteArrayPool
.
useInstance
{
readFully
(
it
,
offset
,
length
)
readFully
(
it
,
offset
,
length
)
consumer
(
it
.
decryptBy
(
key
,
length
))
consumer
(
it
.
decryptBy
(
key
,
length
))
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/PlatformSocket.kt
0 → 100644
View file @
78ee01de
package
net.mamoe.mirai.utils.io
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
import
kotlinx.io.errors.IOException
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 多平台适配的 TCP Socket.
*/
@MiraiInternalAPI
expect
class
PlatformSocket
()
:
Closeable
{
suspend
fun
connect
(
serverHost
:
String
,
serverPort
:
Int
)
/**
* @throws SendPacketInternalException
*/
suspend
inline
fun
send
(
packet
:
ByteReadPacket
)
/**
* @throws ReadPacketInternalException
*/
suspend
inline
fun
read
():
ByteReadPacket
val
isOpen
:
Boolean
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/cryptor/ECDHJvm.kt
View file @
78ee01de
package
net.mamoe.mirai.utils.cryptor
package
net.mamoe.mirai.utils.cryptor
import
net.mamoe.mirai.utils.md5
import
net.mamoe.mirai.utils.md5
import
org.bouncycastle.jce.provider.BouncyCastleProvider
import
java.security.*
import
java.security.*
import
java.security.spec.ECGenParameterSpec
import
java.security.spec.X509EncodedKeySpec
import
java.security.spec.X509EncodedKeySpec
import
javax.crypto.KeyAgreement
import
javax.crypto.KeyAgreement
...
@@ -15,7 +17,7 @@ actual class ECDHKeyPair(
...
@@ -15,7 +17,7 @@ actual class ECDHKeyPair(
actual
val
privateKey
:
ECDHPrivateKey
get
()
=
delegate
.
private
actual
val
privateKey
:
ECDHPrivateKey
get
()
=
delegate
.
private
actual
val
publicKey
:
ECDHPublicKey
get
()
=
delegate
.
public
actual
val
publicKey
:
ECDHPublicKey
get
()
=
delegate
.
public
actual
val
shareKey
:
ByteArray
=
ECDH
.
calculateShareKey
(
privateKey
,
p
ublicKey
)
actual
val
shareKey
:
ByteArray
=
ECDH
.
calculateShareKey
(
privateKey
,
initialP
ublicKey
)
}
}
@Suppress
(
"FunctionName"
)
@Suppress
(
"FunctionName"
)
...
@@ -23,8 +25,12 @@ actual fun ECDH() = ECDH(ECDH.generateKeyPair())
...
@@ -23,8 +25,12 @@ actual fun ECDH() = ECDH(ECDH.generateKeyPair())
actual
class
ECDH
actual
constructor
(
actual
val
keyPair
:
ECDHKeyPair
)
{
actual
class
ECDH
actual
constructor
(
actual
val
keyPair
:
ECDHKeyPair
)
{
actual
companion
object
{
actual
companion
object
{
init
{
Security
.
addProvider
(
BouncyCastleProvider
())
}
actual
fun
generateKeyPair
():
ECDHKeyPair
{
actual
fun
generateKeyPair
():
ECDHKeyPair
{
return
ECDHKeyPair
(
KeyPairGenerator
.
getInstance
(
"EC
DH"
)
.
genKeyPair
())
return
ECDHKeyPair
(
KeyPairGenerator
.
getInstance
(
"EC
"
,
"BC"
).
apply
{
initialize
(
ECGenParameterSpec
(
"secp192k1"
))
}
.
genKeyPair
())
}
}
actual
fun
calculateShareKey
(
actual
fun
calculateShareKey
(
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/io/PlatformSocket.kt
0 → 100644
View file @
78ee01de
package
net.mamoe.mirai.utils.io
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.io.ByteReadChannel
import
kotlinx.coroutines.io.ByteWriteChannel
import
kotlinx.coroutines.io.readAvailable
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Closeable
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.utils.MiraiInternalAPI
/**
* 多平台适配的 TCP Socket.
*/
@MiraiInternalAPI
actual
class
PlatformSocket
:
Closeable
{
@UseExperimental
(
KtorExperimentalAPI
::
class
)
lateinit
var
socket
:
Socket
@UseExperimental
(
KtorExperimentalAPI
::
class
)
actual
val
isOpen
:
Boolean
get
()
=
socket
.
socketContext
.
isActive
override
fun
close
()
=
socket
.
dispose
()
@PublishedApi
internal
lateinit
var
writeChannel
:
ByteWriteChannel
@PublishedApi
internal
lateinit
var
readChannel
:
ByteReadChannel
/**
* @throws SendPacketInternalException
*/
actual
suspend
inline
fun
send
(
packet
:
ByteReadPacket
)
{
writeChannel
.
writePacket
(
packet
)
}
/**
* @throws ReadPacketInternalException
*/
actual
suspend
inline
fun
read
():
ByteReadPacket
{
// do not use readChannel.readRemaining() !!! this function never returns
ByteArrayPool
.
useInstance
{
buffer
->
val
count
=
readChannel
.
readAvailable
(
buffer
)
return
buffer
.
toReadPacket
(
0
,
count
)
}
}
@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
)
writeChannel
=
socket
.
openWriteChannel
(
true
)
readChannel
=
socket
.
openReadChannel
()
}
}
\ No newline at end of file
mirai-core/src/
commonTest/kotlin/net.mamoe.mirai.utils.io
/TypeConversionTest.kt
→
mirai-core/src/
jvmTest/kotlin/net/mamoe/mirai/utils
/TypeConversionTest.kt
View file @
78ee01de
package
net.mamoe.mirai.utils
.io
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.utils.io.hexToBytes
import
net.mamoe.mirai.utils.io.toByteArray
import
net.mamoe.mirai.utils.io.toUHexString
import
kotlin.test.Test
import
kotlin.test.Test
import
kotlin.test.assertEquals
import
kotlin.test.assertEquals
import
kotlin.test.assertTrue
class
TypeConversionTest
{
class
TypeConversionTest
{
...
@@ -13,6 +17,7 @@ class TypeConversionTest {
...
@@ -13,6 +17,7 @@ class TypeConversionTest {
assertEquals
(
"7F"
,
byteArrayOf
(
0
x7F
).
toUHexString
())
assertEquals
(
"7F"
,
byteArrayOf
(
0
x7F
).
toUHexString
())
assertEquals
(
"FF"
,
ubyteArrayOf
(
0
xffu
).
toUHexString
())
assertEquals
(
"FF"
,
ubyteArrayOf
(
0
xffu
).
toUHexString
())
assertEquals
(
"7F"
,
ubyteArrayOf
(
0
x7fu
).
toUHexString
())
assertEquals
(
"7F"
,
ubyteArrayOf
(
0
x7fu
).
toUHexString
())
assertTrue
{
1994701021
.
toByteArray
().
contentEquals
(
"76 E4 B8 DD"
.
hexToBytes
())
}
assertEquals
(
byteArrayOf
(
0
,
0
,
0
,
0
x01
).
toUHexString
(),
1
.
toByteArray
().
toUHexString
())
assertEquals
(
byteArrayOf
(
0
,
0
,
0
,
0
x01
).
toUHexString
(),
1
.
toByteArray
().
toUHexString
())
assertEquals
(
ubyteArrayOf
(
0
x7fu
,
0
xffu
,
0
xffu
,
0
xffu
).
toByteArray
().
toUHexString
(),
Int
.
MAX_VALUE
.
toByteArray
().
toUHexString
())
assertEquals
(
ubyteArrayOf
(
0
x7fu
,
0
xffu
,
0
xffu
,
0
xffu
).
toByteArray
().
toUHexString
(),
Int
.
MAX_VALUE
.
toByteArray
().
toUHexString
())
}
}
...
...
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