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
0e150cdc
Commit
0e150cdc
authored
Jan 23, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Congratulations!! QQAndroid logon successful
parent
434e6511
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
491 additions
and
157 deletions
+491
-157
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
...moe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
+1
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+8
-11
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceInput.kt
...n/kotlin/net/mamoe/mirai/qqandroid/network/io/JceInput.kt
+36
-35
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt
.../kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt
+5
-4
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt
.../kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt
...oe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt
+4
-4
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+28
-21
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/SvcReqRegisterPacket.kt
...oid/network/protocol/packet/login/SvcReqRegisterPacket.kt
+50
-54
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/Proto.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/cryptor/Proto.kt
+42
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt
+7
-5
mirai-debug/src/test/java/jce/jce/JceInputStream.java
mirai-debug/src/test/java/jce/jce/JceInputStream.java
+2
-0
mirai-debug/src/test/java/jce/jce/JceOutputStream.java
mirai-debug/src/test/java/jce/jce/JceOutputStream.java
+12
-12
mirai-debug/src/test/kotlin/jceTest/JceInputTest.kt
mirai-debug/src/test/kotlin/jceTest/JceInputTest.kt
+287
-0
mirai-debug/src/test/kotlin/jceTest/JceOutputTest.kt
mirai-debug/src/test/kotlin/jceTest/JceOutputTest.kt
+8
-6
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt
View file @
0e150cdc
...
...
@@ -11,7 +11,6 @@ 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.RegPushReason
import
net.mamoe.mirai.qqandroid.network.protocol.packet.login.SvcReqRegisterPacket
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.*
...
...
@@ -39,7 +38,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
println
()
println
()
println
(
"Sending ReqRegister"
)
SvcReqRegisterPacket
(
bot
.
client
,
RegPushReason
.
setOnlineStatus
).
sendAndExpect
<
SvcReqRegisterPacket
.
Response
>()
SvcReqRegisterPacket
(
bot
.
client
).
sendAndExpect
<
SvcReqRegisterPacket
.
Response
>()
}
/**
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
0e150cdc
...
...
@@ -4,7 +4,6 @@ import kotlinx.atomicfu.AtomicInt
import
kotlinx.atomicfu.atomic
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.toByteArray
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.BotAccount
import
net.mamoe.mirai.data.OnlineStatus
import
net.mamoe.mirai.qqandroid.QQAndroidBot
...
...
@@ -21,7 +20,10 @@ import net.mamoe.mirai.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.cryptor.decryptBy
import
net.mamoe.mirai.utils.cryptor.initialPublicKey
import
net.mamoe.mirai.utils.getValue
import
net.mamoe.mirai.utils.io.*
import
net.mamoe.mirai.utils.io.hexToBytes
import
net.mamoe.mirai.utils.io.read
import
net.mamoe.mirai.utils.io.readUShortLVByteArray
import
net.mamoe.mirai.utils.io.readUShortLVString
import
net.mamoe.mirai.utils.unsafeWeakRef
/*
...
...
@@ -64,16 +66,11 @@ internal open class QQAndroidClient(
)
}
internal
inline
fun
<
R
>
tryDecryptOrNull
(
data
:
ByteReadPacket
,
mapper
:
(
ByteArray
)
->
R
):
R
?
{
ByteArrayPool
.
useInstance
{
data
.
readAvailable
(
it
)
keys
.
forEach
{
(
key
,
value
)
->
kotlin
.
runCatching
{
return
mapper
(
it
.
decryptBy
(
value
).
also
{
PacketLogger
.
verbose
(
"成功使用 $key 解密"
)
})
}
internal
inline
fun
<
R
>
tryDecryptOrNull
(
data
:
ByteArray
,
size
:
Int
=
data
.
size
,
mapper
:
(
ByteArray
)
->
R
):
R
?
{
keys
.
forEach
{
(
key
,
value
)
->
kotlin
.
runCatching
{
return
mapper
(
data
.
decryptBy
(
value
,
size
).
also
{
PacketLogger
.
verbose
(
"成功使用 $key 解密"
)
})
}
}
return
null
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceInput.kt
View file @
0e150cdc
package
net.mamoe.mirai.qqandroid.network.io
import
kotlinx.io.charsets.Charset
import
kotlinx.io.core.*
import
kotlinx.io.pool.ObjectPool
import
net.mamoe.mirai.utils.io.readString
import
net.mamoe.mirai.utils.io.toIoBuffer
import
kotlin.experimental.and
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
inline
class
JceHead
(
private
val
value
:
Long
)
{
...
...
@@ -12,17 +12,23 @@ inline class JceHead(private val value: Long) {
val
tag
:
Int
get
()
=
(
value
ushr
32
).
toInt
()
val
type
:
Byte
get
()
=
value
.
toUInt
().
toByte
()
override
fun
toString
():
String
{
return
"JceHead(tag=$tag, type=$type)"
}
}
fun
ByteArray
.
asJceInput
(
):
JceInput
=
JceInput
(
this
.
toIoBuffer
()
)
fun
ByteArray
.
asJceInput
(
charset
:
Charset
=
CharsetGBK
):
JceInput
=
JceInput
(
this
.
toIoBuffer
(),
charset
)
@Suppress
(
"MemberVisibilityCanBePrivate"
)
@UseExperimental
(
ExperimentalUnsignedTypes
::
class
)
class
JceInput
(
@PublishedApi
internal
val
input
:
IoBuffer
,
private
val
charset
:
Charset
=
CharsetGBK
,
private
val
pool
:
ObjectPool
<
IoBuffer
>
=
IoBuffer
.
Pool
)
:
Closeable
{
constructor
(
input
:
Input
)
:
this
(
IoBuffer
.
Pool
.
borrow
().
also
{
input
.
readAvailable
(
it
)
})
override
fun
close
()
{
...
...
@@ -36,12 +42,12 @@ class JceInput(
internal
fun
peakHead
():
JceHead
=
input
.
makeView
().
readHead
()
private
fun
IoBuffer
.
readHead
():
JceHead
{
val
var2
=
readByte
()
val
type
=
var2
and
15
var
tag
=
(
var2
.
toInt
()
and
240
)
shr
4
if
(
tag
==
15
)
tag
=
read
Byte
().
toInt
()
and
255
return
JceHead
(
tag
=
tag
,
type
=
type
)
val
var2
=
read
U
Byte
()
val
type
=
var2
and
15
u
var
tag
=
var2
.
toUInt
(
)
shr
4
if
(
tag
==
15
u
)
tag
=
read
UByte
().
toUInt
()
return
JceHead
(
tag
=
tag
.
toInt
(),
type
=
type
.
toByte
()
)
}
fun
read
(
default
:
Byte
,
tag
:
Int
):
Byte
=
readByteOrNull
(
tag
)
?:
default
...
...
@@ -79,7 +85,7 @@ class JceInput(
fun
readBooleanArray
(
tag
:
Int
):
BooleanArray
=
readBooleanArrayOrNull
(
tag
)
?:
error
(
"cannot find tag $tag"
)
fun
<
K
,
V
>
readMap
(
defaultKey
:
K
,
defaultValue
:
V
,
tag
:
Int
):
Map
<
K
,
V
>
=
readMapOrNull
(
defaultKey
,
defaultValue
,
tag
)
?:
error
(
"cannot find tag $tag"
)
fun
<
T
>
readList
(
defaultElement
:
T
,
tag
:
Int
):
List
<
T
>
=
readListOrNull
(
defaultElement
,
tag
)
?:
error
(
"cannot find tag $tag"
)
fun
<
T
>
readSimpleArray
(
defaultElement
:
T
,
tag
:
Int
):
Array
<
T
>
=
readArrayOrNull
(
defaultElement
,
tag
)
?:
error
(
"cannot find tag $tag"
)
inline
fun
<
reified
T
>
readSimpleArray
(
defaultElement
:
T
,
tag
:
Int
):
Array
<
T
>
=
readArrayOrNull
(
defaultElement
,
tag
)
?:
error
(
"cannot find tag $tag"
)
fun
<
J
:
JceStruct
>
readJceStruct
(
factory
:
JceStruct
.
Factory
<
J
>,
tag
:
Int
):
J
=
readJceStructOrNull
(
factory
,
tag
)
?:
error
(
"cannot find tag $tag"
)
fun
readStringArray
(
tag
:
Int
):
Array
<
String
>
=
readArrayOrNull
(
""
,
tag
)
?:
error
(
"cannot find tag $tag"
)
...
...
@@ -142,7 +148,7 @@ class JceInput(
fun
readByteArrayOrNull
(
tag
:
Int
):
ByteArray
?
=
skipToTagOrNull
(
tag
)
{
when
(
it
.
type
.
toInt
())
{
9
->
ByteArray
(
input
.
readInt
())
{
readByte
(
tag
)
}
9
->
ByteArray
(
readInt
(
0
))
{
readByte
(
0
)
}
13
->
{
val
head
=
readHead
()
check
(
head
.
type
.
toInt
()
==
0
)
{
"type mismatch"
}
...
...
@@ -154,56 +160,56 @@ class JceInput(
fun
readShortArrayOrNull
(
tag
:
Int
):
ShortArray
?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
ShortArray
(
input
.
readInt
())
{
readShort
(
tag
)
}
ShortArray
(
readInt
(
0
))
{
readShort
(
0
)
}
}
fun
readDoubleArrayOrNull
(
tag
:
Int
):
DoubleArray
?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
DoubleArray
(
input
.
readInt
())
{
readDouble
(
tag
)
}
DoubleArray
(
readInt
(
0
))
{
readDouble
(
0
)
}
}
fun
readFloatArrayOrNull
(
tag
:
Int
):
FloatArray
?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
FloatArray
(
input
.
readInt
())
{
readFloat
(
tag
)
}
FloatArray
(
readInt
(
0
))
{
readFloat
(
0
)
}
}
fun
readIntArrayOrNull
(
tag
:
Int
):
IntArray
?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
IntArray
(
input
.
readInt
())
{
readInt
(
tag
)
}
IntArray
(
readInt
(
0
))
{
readInt
(
0
)
}
}
fun
readLongArrayOrNull
(
tag
:
Int
):
LongArray
?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
LongArray
(
input
.
readInt
())
{
readLong
(
tag
)
}
LongArray
(
readInt
(
0
))
{
readLong
(
0
)
}
}
@Suppress
(
"UNCHECKED_CAST"
)
inline
fun
<
reified
T
>
readArrayOrNull
(
tag
:
Int
):
Array
<
T
>?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
Array
(
input
.
readInt
())
{
readSimpleObject
<
T
>(
tag
)
}
Array
(
readInt
(
0
))
{
readSimpleObject
<
T
>(
0
)
}
}
@Suppress
(
"UNCHECKED_CAST"
)
fun
<
T
>
readArrayOrNull
(
defaultElement
:
T
,
tag
:
Int
):
Array
<
T
>?
=
skipToTagOrNull
(
tag
)
{
inline
fun
<
reified
T
>
readArrayOrNull
(
defaultElement
:
T
,
tag
:
Int
):
Array
<
T
>?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
Array
(
input
.
readInt
())
{
readObject
(
defaultElement
,
tag
)
as
Any
}
as
Array
<
T
>
Array
(
readInt
(
0
))
{
readObject
(
defaultElement
,
0
)
}
}
@Suppress
(
"UNCHECKED_CAST"
)
fun
<
J
:
JceStruct
>
readJceStructArrayOrNull
(
factory
:
JceStruct
.
Factory
<
J
>,
tag
:
Int
):
Array
<
J
>?
=
skipToTagOrNull
(
tag
)
{
inline
fun
<
reified
J
:
JceStruct
>
readJceStructArrayOrNull
(
factory
:
JceStruct
.
Factory
<
J
>,
tag
:
Int
):
Array
<
J
>?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
Array
(
input
.
readInt
())
{
readObject
(
factory
,
tag
)
as
Any
}
as
Array
<
J
>
Array
(
readInt
(
0
))
{
readJceStruct
(
factory
,
0
)
}
}
fun
readBooleanArrayOrNull
(
tag
:
Int
):
BooleanArray
?
=
skipToTagOrNull
(
tag
)
{
require
(
it
.
type
.
toInt
()
==
9
)
{
"type mismatch"
}
BooleanArray
(
input
.
readInt
())
{
readBoolean
(
tag
)
}
BooleanArray
(
readInt
(
0
))
{
readBoolean
(
0
)
}
}
fun
readStringOrNull
(
tag
:
Int
):
String
?
=
skipToTagOrNull
(
tag
)
{
head
->
return
when
(
head
.
type
.
toInt
())
{
6
->
input
.
readString
(
input
.
readUByte
().
toInt
())
7
->
input
.
readString
(
input
.
readUInt
().
also
{
require
(
it
.
toInt
()
in
1
until
104857600
)
{
"bad string length: $it"
}
}.
toInt
()
)
6
->
input
.
readString
(
input
.
readUByte
().
toInt
()
,
charset
=
charset
)
7
->
input
.
readString
(
input
.
readUInt
().
toInt
().
also
{
require
(
it
in
1
until
104857600
)
{
"bad string length: $it"
}
},
charset
=
charset
)
else
->
error
(
"type mismatch: ${head.type}"
)
}
}
...
...
@@ -233,7 +239,7 @@ class JceInput(
val
size
=
readInt
(
0
)
val
list
=
ArrayList
<
T
>(
size
)
repeat
(
size
)
{
list
[
it
]
=
readObject
(
defaultElement
,
tag
)
list
.
add
(
readObject
(
defaultElement
,
0
)
)
}
return
list
}
...
...
@@ -267,9 +273,8 @@ class JceInput(
is
ByteArray
->
readByteArray
(
tag
)
is
FloatArray
->
readByteArray
(
tag
)
is
DoubleArray
->
readDoubleArrayOrNull
(
tag
)
is
JceStruct
.
Factory
<
JceStruct
>
->
readJceStruct
(
default
,
tag
)
as
T
is
List
<
*
>
->
{
readList
(
default
[
0
]
,
tag
)
readList
(
default
,
tag
)
}
is
Map
<
*
,
*
>
->
{
val
entry
=
default
.
entries
.
first
()
...
...
@@ -325,19 +330,13 @@ class JceInput(
6
->
this
.
input
.
discardExact
(
this
.
input
.
readUByte
().
toInt
())
7
->
this
.
input
.
discardExact
(
this
.
input
.
readInt
())
8
->
{
// map
val
length
=
this
.
readInt
(
0
)
var
read
=
0
while
(
read
<
length
*
2
)
{
repeat
(
this
.
readInt
(
0
)
*
2
)
{
skipField
()
++
read
}
}
9
->
{
// list
val
length
=
this
.
readInt
(
0
)
var
read
=
0
while
(
read
<
length
)
{
repeat
(
this
.
readInt
(
0
))
{
skipField
()
++
read
}
}
10
->
this
.
skipToStructEnd
()
...
...
@@ -360,8 +359,10 @@ private inline fun <R> JceInput.skipToTag(tag: Int, block: (JceHead) -> R): R {
@PublishedApi
internal
inline
fun
<
R
>
JceInput
.
skipToTagOrNull
(
tag
:
Int
,
block
:
(
JceHead
)
->
R
):
R
?
{
while
(
true
)
{
if
(
this
.
input
.
endOfInput
)
if
(
this
.
input
.
endOfInput
)
{
println
(
"endOfInput"
)
return
null
}
val
head
=
peakHead
()
if
(
head
.
tag
>
tag
)
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceOutput.kt
View file @
0e150cdc
...
...
@@ -2,6 +2,7 @@ package net.mamoe.mirai.qqandroid.network.io
import
kotlinx.io.charsets.Charset
import
kotlinx.io.core.*
import
kotlin.experimental.or
import
kotlin.reflect.KClass
@PublishedApi
...
...
@@ -45,7 +46,7 @@ class JceOutput(
fun
writeByte
(
v
:
Byte
,
tag
:
Int
)
{
if
(
v
.
toInt
()
==
0
)
{
writeHead
(
ZERO_T
AG
,
tag
)
writeHead
(
ZERO_T
YPE
,
tag
)
}
else
{
writeHead
(
BYTE
,
tag
)
output
.
writeByte
(
v
)
...
...
@@ -147,7 +148,7 @@ class JceOutput(
if
(
v
in
Byte
.
MIN_VALUE
..
Byte
.
MAX_VALUE
)
{
writeByte
(
v
.
toByte
(),
tag
)
}
else
{
writeHead
(
BYTE
,
tag
)
writeHead
(
SHORT
,
tag
)
output
.
writeShort
(
v
)
}
}
...
...
@@ -266,7 +267,7 @@ class JceOutput(
const
val
STRING4
:
Int
=
7
const
val
STRUCT_BEGIN
:
Int
=
10
const
val
STRUCT_END
:
Int
=
11
const
val
ZERO_T
AG
:
Int
=
12
const
val
ZERO_T
YPE
:
Int
=
12
private
fun
Any
?.
getClassName
():
KClass
<
out
Any
>
=
if
(
this
==
null
)
Unit
::
class
else this::class
}
...
...
@@ -278,7 +279,7 @@ class JceOutput(
return
}
if
(
tag
<
256
)
{
this
.
output
.
writeByte
((
type
or
0
xF0
).
toByte
(
))
this
.
output
.
writeByte
((
type
.
toByte
()
or
0
xF0
.
toByte
()
))
this
.
output
.
writeByte
(
tag
.
toByte
())
return
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/io/JceStruct.kt
View file @
0e150cdc
...
...
@@ -3,7 +3,7 @@ package net.mamoe.mirai.qqandroid.network.io
abstract
class
JceStruct
{
abstract
fun
writeTo
(
builder
:
JceOutput
)
interface
Factory
<
out
T
:
JceStruct
>
{
interface
Factory
<
out
T
:
JceStruct
>
{
fun
newInstanceFrom
(
input
:
JceInput
):
T
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/jce/SvcReqRegister.kt
View file @
0e150cdc
...
...
@@ -26,12 +26,12 @@ class SvcReqRegister(
var
lBid
:
Long
=
0L
,
var
lCpId
:
Long
=
0L
,
var
lUin
:
Long
=
0L
,
var
sBuildVer
:
String
?
=
null
,
var
sChannelNo
:
String
?
=
null
,
var
sBuildVer
:
String
?
=
""
,
var
sChannelNo
:
String
?
=
""
,
var
sOther
:
String
=
""
,
var
strDevName
:
String
?
=
null
,
var
strDevType
:
String
?
=
null
,
var
strIOSIdfa
:
String
?
=
null
,
var
strIOSIdfa
:
String
?
=
""
,
var
strOSVer
:
String
?
=
null
,
var
strVendorName
:
String
?
=
null
,
var
strVendorOSName
:
String
?
=
null
,
...
...
@@ -59,7 +59,7 @@ class SvcReqRegister(
this
.
timeStamp
=
input
.
readLong
(
10
)
this
.
iOSVersion
=
input
.
readLong
(
11
)
this
.
cNetType
=
input
.
readByte
(
12
)
this
.
sBuildVer
=
input
.
readString
(
13
)
this
.
sBuildVer
=
input
.
readString
OrNull
(
13
)
this
.
bRegType
=
input
.
readByte
(
14
)
this
.
vecDevParam
=
input
.
readByteArrayOrNull
(
15
)
this
.
vecGuid
=
input
.
readByteArrayOrNull
(
16
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
0e150cdc
...
...
@@ -64,7 +64,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
* full packet without length
*/
// do not inline. Exceptions thrown will not be reported correctly
suspend
fun
parseIncomingPacket
(
bot
:
QQAndroidBot
,
rawInput
:
Input
,
consumer
:
PacketConsumer
)
{
suspend
fun
parseIncomingPacket
(
bot
:
QQAndroidBot
,
rawInput
:
Input
,
consumer
:
PacketConsumer
)
:
Unit
{
rawInput
.
readBytes
().
let
{
PacketLogger
.
verbose
(
"开始处理包: ${it.toUHexString()}"
)
it
.
toReadPacket
()
...
...
@@ -89,28 +89,34 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
//debugPrint("remaining")
(
if
(
flag2
==
2
)
{
PacketLogger
.
verbose
(
"SSO, 尝试使用 16 zero 解密."
)
kotlin
.
runCatching
{
decryptBy
(
DECRYPTER_16_ZERO
).
also
{
PacketLogger
.
verbose
(
"成功使用 16 zero 解密"
)
}
}
}
else
{
PacketLogger
.
verbose
(
"Uni, 尝试使用 d2Key 解密."
)
kotlin
.
runCatching
{
decryptBy
(
bot
.
client
.
wLoginSigInfo
.
d2Key
).
also
{
PacketLogger
.
verbose
(
"成功使用 d2Key 解密"
)
}
ByteArrayPool
.
useInstance
{
data
->
val
size
=
this
.
readAvailable
(
data
)
(
if
(
flag2
==
2
)
{
PacketLogger
.
verbose
(
"SSO, 尝试使用 16 zero 解密."
)
kotlin
.
runCatching
{
data
.
decryptBy
(
DECRYPTER_16_ZERO
,
size
).
also
{
PacketLogger
.
verbose
(
"成功使用 16 zero 解密"
)
}
}
}
else
{
PacketLogger
.
verbose
(
"Uni, 尝试使用 d2Key 解密."
)
kotlin
.
runCatching
{
data
.
decryptBy
(
bot
.
client
.
wLoginSigInfo
.
d2Key
,
size
).
also
{
PacketLogger
.
verbose
(
"成功使用 d2Key 解密"
)
}
}
}).
getOrElse
{
PacketLogger
.
verbose
(
"失败, 尝试其他各种key"
)
bot
.
client
.
tryDecryptOrNull
(
data
)
{
it
}
}
?.
toReadPacket
()
?.
also
{
decryptedData
->
when
(
flag1
)
{
0
x0A
->
parseLoginSsoPacket
(
bot
,
decryptedData
,
consumer
)
0
x0B
->
parseUniPacket
(
bot
,
decryptedData
,
consumer
)
}
}
?:
inline
{
PacketLogger
.
error
(
"任何key都无法解密: ${data.toUHexString()}"
)
return
}
}).
getOrElse
{
PacketLogger
.
verbose
(
"失败, 尝试其他各种key"
)
bot
.
client
.
tryDecryptOrNull
(
this
)
{
it
.
toReadPacket
()
}
}
?.
also
{
decryptedData
->
when
(
flag1
)
{
0
x0A
->
parseLoginSsoPacket
(
bot
,
decryptedData
,
consumer
)
0
x0B
->
parseUniPacket
(
bot
,
decryptedData
,
consumer
)
}
}
?:
inline
{
PacketLogger
.
error
(
"任何key都无法解密"
)
return
}
Unit
}
}
...
...
@@ -155,6 +161,7 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
if
(
packetFactory
==
null
)
{
bot
.
logger
.
warning
(
"找不到包 PacketFactory"
)
PacketLogger
.
verbose
(
"最外层解密后的 body = ${this.readBytes().toUHexString()}"
)
return
}
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/login/SvcReqRegisterPacket.kt
View file @
0e150cdc
package
net.mamoe.mirai.qqandroid.network.protocol.packet.login
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.readBytes
import
kotlinx.serialization.protobuf.ProtoBuf
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.io.buildJcePacket
import
net.mamoe.mirai.qqandroid.network.io.jceMap
import
net.mamoe.mirai.qqandroid.network.io.jceStruct
import
net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
...
...
@@ -17,7 +15,6 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacke
import
net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import
net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import
net.mamoe.mirai.qqandroid.utils.NetworkType
import
net.mamoe.mirai.utils.currentTimeSeconds
import
net.mamoe.mirai.utils.io.debugPrint
import
net.mamoe.mirai.utils.io.encodeToString
import
net.mamoe.mirai.utils.io.toReadPacket
...
...
@@ -64,65 +61,64 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
sFuncName
=
"SvcReqRegister"
sBuffer
=
jceMap
(
0
,
"SvcReqRegister"
to
buildJcePacket
{
writeObject
(
jceStruct
(
0
,
SvcReqRegister
(
cConnType
=
0
,
lBid
=
1
or
2
or
4
,
lUin
=
client
.
uin
,
iStatus
=
client
.
onlineStatus
.
id
,
bKikPC
=
0
,
// 是否把 PC 踢下线
bKikWeak
=
0
,
timeStamp
=
currentTimeSeconds
,
// millis or seconds??
iLargeSeq
=
1551
,
// ?
bOpenPush
=
1
,
iLocaleID
=
2052
,
bRegType
=
"SvcReqRegister"
to
jceStruct
(
0
,
SvcReqRegister
().
apply
{
cConnType
=
0
lBid
=
1
or
2
or
4
lUin
=
client
.
uin
iStatus
=
client
.
onlineStatus
.
id
bKikPC
=
0
// 是否把 PC 踢下线
bKikWeak
=
0
timeStamp
=
0
// timeStamp = currentTimeSeconds
// millis or seconds??
iLargeSeq
=
1551
// ?
bOpenPush
=
1
iLocaleID
=
2052
bRegType
=
(
if
(
regPushReason
==
RegPushReason
.
appRegister
||
regPushReason
==
RegPushReason
.
fillRegProxy
||
regPushReason
==
RegPushReason
.
createDefaultRegInfo
||
regPushReason
==
RegPushReason
.
setOnlineStatus
)
0
else
1
).
toByte
()
,
bIsSetStatus
=
if
(
regPushReason
==
RegPushReason
.
setOnlineStatus
)
1
else
0
,
iOSVersion
=
client
.
device
.
version
.
sdk
.
toLong
(),
cNetType
=
if
(
client
.
networkType
==
NetworkType
.
WIFI
)
1
else
0
,
vecGuid
=
client
.
device
.
guid
,
strDevName
=
client
.
device
.
model
.
encodeToString
(),
strDevType
=
client
.
device
.
model
.
encodeToString
(),
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
(),
)
0
else
1
).
toByte
()
bIsSetStatus
=
if
(
regPushReason
==
RegPushReason
.
setOnlineStatus
)
1
else
0
iOSVersion
=
client
.
device
.
version
.
sdk
.
toLong
()
cNetType
=
if
(
client
.
networkType
==
NetworkType
.
WIFI
)
1
else
0
vecGuid
=
client
.
device
.
guid
strDevName
=
client
.
device
.
model
.
encodeToString
()
strDevType
=
client
.
device
.
model
.
encodeToString
()
strOSVer
=
client
.
device
.
version
.
release
.
encodeToString
()
uOldSSOIp
=
0
,
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
},
strVendorName
=
"MIUI"
,
strVendorOSName
=
"?ONEPLUS A5000_23_17"
,
// register 时还需要
/*
var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/
bytes_0x769_reqbody
=
ProtoBuf
.
dump
(
Oidb0x769
.
RequestBody
.
serializer
(),
Oidb0x769
.
RequestBody
(
rpt_config_list
=
listOf
(
Oidb0x769
.
ConfigSeq
(
type
=
46
,
version
=
0
),
Oidb0x769
.
ConfigSeq
(
type
=
283
,
version
=
0
)
uOldSSOIp
=
0
uNewSSOIp
=
localIpAddress
().
split
(
"."
).
foldIndexed
(
0L
)
{
index
:
Int
,
acc
:
Long
,
s
:
String
->
acc
or
((
s
.
toLong
()
shl
(
index
*
16
)))
}
strVendorName
=
"MIUI"
strVendorOSName
=
"?ONEPLUS A5000_23_17"
// register 时还需要
/*
var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/
bytes_0x769_reqbody
=
ProtoBuf
.
dump
(
Oidb0x769
.
RequestBody
.
serializer
(),
Oidb0x769
.
RequestBody
(
rpt_config_list
=
listOf
(
Oidb0x769
.
ConfigSeq
(
type
=
46
,
version
=
0
),
Oidb0x769
.
ConfigSeq
(
type
=
283
,
version
=
0
)
)
),
bSetMute
=
0
)
)
),
0
)
}.
readBytes
()
bSetMute
=
0
}
)
)
}
this
.
writePacket
(
this
.
build
().
debugPrint
(
"sso body"
))
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/cryptor/Proto.kt
View file @
0e150cdc
...
...
@@ -152,11 +152,51 @@ fun Any?.contentToString(prefix: String = ""): String = when (this) {
is
ByteArray
->
{
if
(
this
.
size
==
0
)
"<Empty ByteArray>"
else
this
.
toUHexString
()
// + " (${this.encodeToString()})"
else
this
.
toUHexString
()
}
is
UByteArray
->
{
if
(
this
.
size
==
0
)
"<Empty UByteArray>"
else
this
.
toUHexString
()
// + " (${this.encodeToString()})"
else
this
.
toUHexString
()
}
is
ShortArray
->
{
if
(
this
.
size
==
0
)
"<Empty ShortArray>"
else
this
.
iterator
().
contentToString
()
}
is
IntArray
->
{
if
(
this
.
size
==
0
)
"<Empty IntArray>"
else
this
.
iterator
().
contentToString
()
}
is
LongArray
->
{
if
(
this
.
size
==
0
)
"<Empty LongArray>"
else
this
.
iterator
().
contentToString
()
}
is
FloatArray
->
{
if
(
this
.
size
==
0
)
"<Empty FloatArray>"
else
this
.
iterator
().
contentToString
()
}
is
DoubleArray
->
{
if
(
this
.
size
==
0
)
"<Empty DoubleArray>"
else
this
.
iterator
().
contentToString
()
}
is
UShortArray
->
{
if
(
this
.
size
==
0
)
"<Empty ShortArray>"
else
this
.
iterator
().
contentToString
()
}
is
UIntArray
->
{
if
(
this
.
size
==
0
)
"<Empty IntArray>"
else
this
.
iterator
().
contentToString
()
}
is
ULongArray
->
{
if
(
this
.
size
==
0
)
"<Empty LongArray>"
else
this
.
iterator
().
contentToString
()
}
is
Array
<
*
>
->
{
if
(
this
.
size
==
0
)
"<Empty Array>"
else
this
.
iterator
().
contentToString
()
}
is
BooleanArray
->
{
if
(
this
.
size
==
0
)
"<Empty BooleanArray>"
else
this
.
iterator
().
contentToString
()
}
is
ProtoMap
->
"ProtoMap(size=$size){\n"
+
this
.
toStringPrefixed
(
"$prefix${ProtoMap.indent}${ProtoMap.indent}"
)
+
"\n$prefix${ProtoMap.indent}}"
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/io/InputUtils.kt
View file @
0e150cdc
...
...
@@ -3,6 +3,8 @@
package
net.mamoe.mirai.utils.io
import
kotlinx.io.OutputStream
import
kotlinx.io.charsets.Charset
import
kotlinx.io.charsets.Charsets
import
kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.contact.GroupId
...
...
@@ -180,13 +182,13 @@ internal inline fun illegalArgument(message: String? = null): Nothing = error(me
fun
Map
<
Int
,
String
>.
printTLVMap
(
name
:
String
=
""
)
=
debugPrintln
(
"TLVMap $name= "
+
this
.
mapKeys
{
it
.
key
.
toInt
().
toUShort
().
toUHexString
()
})
fun
Input
.
readString
(
length
:
Int
):
String
=
String
(
this
.
readBytes
(
length
)
)
fun
Input
.
readString
(
length
:
Long
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
())
)
fun
Input
.
readString
(
length
:
Short
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
())
)
fun
Input
.
readString
(
length
:
Int
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
),
charset
=
charset
)
fun
Input
.
readString
(
length
:
Long
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
fun
Input
.
readString
(
length
:
Short
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
@JvmSynthetic
fun
Input
.
readString
(
length
:
UShort
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
())
)
fun
Input
.
readString
(
length
:
UShort
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
fun
Input
.
readString
(
length
:
Byte
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
())
)
fun
Input
.
readString
(
length
:
Byte
,
charset
:
Charset
=
Charsets
.
UTF_8
):
String
=
String
(
this
.
readBytes
(
length
.
toInt
()),
charset
=
charset
)
@JvmSynthetic
fun
Input
.
readStringUntil
(
stopSignalExclude
:
UByte
,
expectingEOF
:
Boolean
=
false
):
String
=
readStringUntil
(
stopSignalExclude
.
toByte
(),
expectingEOF
)
...
...
mirai-debug/src/test/java/jce/jce/JceInputStream.java
View file @
0e150cdc
...
...
@@ -353,6 +353,8 @@ public final class JceInputStream {
throw
new
JceDecodeException
(
var5
.
getMessage
());
}
System
.
out
.
println
(
var1
.
toString
());
var4
=
new
JceInputStream
$HeadData
();
this
.
readHead
(
var4
);
if
(
var4
.
type
!=
10
)
{
...
...
mirai-debug/src/test/java/jce/jce/JceOutputStream.java
View file @
0e150cdc
...
...
@@ -400,18 +400,18 @@ public class JceOutputStream {
}
}
public
void
writeHead
(
byte
var1
,
int
var2
)
{
byte
var3
;
if
(
var2
<
15
)
{
var3
=
(
byte
)
(
var2
<<
4
|
var1
);
this
.
field_80728
.
put
(
var3
);
}
else
if
(
var2
<
256
)
{
var3
=
(
byte
)
(
var1
|
240
);
this
.
field_80728
.
put
(
var3
);
this
.
field_80728
.
put
((
byte
)
var2
);
}
else
{
throw
new
JceEncodeException
(
"tag is too large: "
+
var2
);
}
public
void
writeHead
(
byte
var1
,
int
tag
)
{
byte
var3
;
if
(
tag
<
15
)
{
var3
=
(
byte
)
(
tag
<<
4
|
var1
);
this
.
field_80728
.
put
(
var3
);
}
else
if
(
tag
<
256
)
{
var3
=
(
byte
)
(
var1
|
240
);
this
.
field_80728
.
put
(
var3
);
this
.
field_80728
.
put
((
byte
)
tag
);
}
else
{
throw
new
JceEncodeException
(
"tag is too large: "
+
tag
);
}
}
public
void
writeStringByte
(
String
var1
,
int
var2
)
{
...
...
mirai-debug/src/test/kotlin/jceTest/JceInputTest.kt
0 → 100644
View file @
0e150cdc
package
jceTest
import
io.ktor.util.InternalAPI
import
jce.jce.JceInputStream
import
jceTest.JceOutputTest.TestMiraiStruct
import
jceTest.JceOutputTest.TestQQStruct
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.qqandroid.network.io.JceInput
import
net.mamoe.mirai.qqandroid.network.io.buildJcePacket
import
net.mamoe.mirai.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.io.toIoBuffer
import
org.junit.Test
private
infix
fun
<
T
>
T
.
shouldEqualTo
(
another
:
T
)
{
if
(
this
is
Array
<
*
>)
{
this
.
contentEquals
(
another
as
Array
<
*
>)
}
else
check
(
this
.
contentToString
()
==
another
.
contentToString
())
{
"""actual: ${this.contentToString()}
|required: ${another.contentToString()}
"""
.
trimMargin
()
}
}
@UseExperimental
(
InternalAPI
::
class
)
private
fun
<
R
>
ByteArray
.
qqJce
(
block
:
JceInputStream
.()
->
R
):
R
{
return
JceInputStream
(
this
).
run
(
block
)
}
private
fun
<
R
>
ByteArray
.
read
(
block
:
JceInput
.()
->
R
):
R
{
return
JceInput
(
this
.
toIoBuffer
()).
run
(
block
)
}
private
fun
ByteReadPacket
.
check
(
block
:
ByteArray
.()
->
Unit
)
{
this
.
readBytes
().
apply
(
block
)
}
internal
class
JceInputTest
{
@Test
fun
readByte
()
=
buildJcePacket
{
writeByte
(
1
,
1
)
}.
check
{
read
{
readByte
(
1
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toByte
(),
1
,
true
)
}
}
@Test
fun
readDouble
()
=
buildJcePacket
{
writeDouble
(
1.0
,
1
)
}.
check
{
read
{
readDouble
(
1
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toDouble
(),
1
,
true
)
}
}
@Test
fun
readFloat
()
=
buildJcePacket
{
writeFloat
(
1.0f
,
1
)
}.
check
{
read
{
readFloat
(
1
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toFloat
(),
1
,
true
)
}
}
@Test
fun
readFully
()
=
buildJcePacket
{
writeFully
(
byteArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readByteArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
byteArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully
()
=
buildJcePacket
{
writeFully
(
shortArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readShortArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
shortArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully1
()
=
buildJcePacket
{
writeFully
(
intArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readIntArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
intArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully2
()
=
buildJcePacket
{
writeFully
(
longArrayOf
(
1
,
2
,
3
),
1
)
}.
check
{
read
{
readLongArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
longArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully3
()
=
buildJcePacket
{
writeFully
(
booleanArrayOf
(
true
,
false
,
true
),
1
)
}.
check
{
read
{
readBooleanArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
booleanArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully4
()
=
buildJcePacket
{
writeFully
(
floatArrayOf
(
1f
,
2f
,
3f
),
1
)
}.
check
{
read
{
readFloatArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
floatArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully5
()
=
buildJcePacket
{
writeFully
(
doubleArrayOf
(
1.0
,
2.0
,
3.0
),
1
)
}.
check
{
read
{
readDoubleArray
(
1
)
}
shouldEqualTo
qqJce
{
read
(
doubleArrayOf
(),
1
,
true
)
}
}
@Test
fun
testWriteFully6
()
=
buildJcePacket
{
writeFully
(
arrayOf
(
"sss"
,
"哈哈"
),
1
)
}.
check
{
read
{
readSimpleArray
(
""
,
1
)
}
shouldEqualTo
qqJce
{
read
(
arrayOf
(
""
),
1
,
true
)
}
}
@Test
fun
testWriteFully7
()
=
buildJcePacket
{
writeFully
(
arrayOf
(
"sss"
,
"哈哈"
),
1
)
}.
check
{
read
{
readArrayOrNull
(
""
,
1
)
!!
}
shouldEqualTo
qqJce
{
read
(
arrayOf
(
""
),
1
,
true
)
}
}
@Test
fun
testWriteFully8
()
=
buildJcePacket
{
writeFully
(
arrayOf
(
TestMiraiStruct
(
"Haha"
)),
1
)
}.
check
{
read
{
readJceStructArrayOrNull
(
TestMiraiStruct
,
1
)
!!
}
shouldEqualTo
qqJce
{
read
(
arrayOf
(
TestQQStruct
(
"stub"
)),
1
,
true
)
}
}
@Test
fun
readInt
()
=
buildJcePacket
{
writeInt
(
1
,
2
)
}.
check
{
read
{
readInt
(
2
)
}
shouldEqualTo
qqJce
{
read
(
0
,
2
,
true
)
}
}
@Test
fun
readLong
()
=
buildJcePacket
{
writeLong
(
1
,
2
)
}.
check
{
read
{
readLong
(
2
)
}
shouldEqualTo
qqJce
{
read
(
0L
,
2
,
true
)
}
}
@Test
fun
readShort
()
=
buildJcePacket
{
writeShort
(
1
,
2
)
}.
check
{
read
{
readShort
(
2
)
}
shouldEqualTo
qqJce
{
read
(
0
.
toShort
(),
2
,
true
)
}
}
@Test
fun
readBoolean
()
=
buildJcePacket
{
writeBoolean
(
true
,
2
)
}.
check
{
read
{
readBoolean
(
2
)
}
shouldEqualTo
qqJce
{
read
(
false
,
2
,
true
)
}
}
@Test
fun
readString
()
=
buildJcePacket
{
writeString
(
"嗨"
,
2
)
}.
check
{
read
{
readString
(
2
)
}
shouldEqualTo
qqJce
{
read
(
""
,
2
,
true
)
}
}
@Test
fun
readMap
()
=
buildJcePacket
{
writeMap
(
mapOf
(
123.0
to
"Hello"
),
3
)
}.
check
{
read
{
readMap
(
0.0
,
""
,
3
)
}
shouldEqualTo
qqJce
{
read
(
mapOf
(
0.0
to
""
),
3
,
true
)
}
}
@Test
fun
readCollection
()
=
buildJcePacket
{
writeCollection
(
listOf
(
"1"
,
"还"
),
3
)
}.
check
{
repeat
(
0
)
{
error
(
"fuck kotlin"
)
}
read
{
readList
(
""
,
3
)
}
shouldEqualTo
qqJce
{
read
(
listOf
(
""
),
3
,
true
)
}
}
@Test
fun
readJceStruct
()
=
buildJcePacket
{
writeJceStruct
(
TestMiraiStruct
(
"123"
),
3
)
}.
check
{
read
{
readJceStruct
(
TestMiraiStruct
,
3
)
}
shouldEqualTo
qqJce
{
read
(
TestQQStruct
(
"stub"
),
3
,
true
)
!!
}
}
@Test
fun
readObject
()
=
buildJcePacket
{
writeObject
(
123
,
3
)
}.
check
{
read
{
readObject
(
123
,
3
)
}
shouldEqualTo
qqJce
{
read
(
123
as
Any
,
3
,
true
)
}
}
}
\ No newline at end of file
mirai-debug/src/test/kotlin/jceTest/
jce
Test.kt
→
mirai-debug/src/test/kotlin/jceTest/
JceOutput
Test.kt
View file @
0e150cdc
...
...
@@ -221,13 +221,9 @@ internal class JceOutputTest {
@Test
fun
writeCollection
()
{
buildJcePacket
{
writeMap
(
mapOf
(
""
to
""
),
1
)
writeMap
(
mapOf
(
""
to
123
),
2
)
writeMap
(
mapOf
(
123.0
to
"Hello"
),
3
)
writeCollection
(
listOf
(
"啊"
,
"333"
,
"1"
),
1
)
}
shouldEqualTo
qqJce
{
write
(
mapOf
(
""
to
""
),
1
)
write
(
mapOf
(
""
to
123
),
2
)
write
(
mapOf
(
123.0
to
"Hello"
),
3
)
write
(
listOf
(
"啊"
,
"333"
,
"1"
),
1
)
}
}
...
...
@@ -248,6 +244,8 @@ internal class JceOutputTest {
class
TestQQStruct
(
private
var
message
:
String
)
:
JceStruct
()
{
constructor
()
:
this
(
""
)
override
fun
readFrom
(
var1
:
JceInputStream
)
{
message
=
var1
.
read
(
""
,
0
,
true
)
}
...
...
@@ -255,6 +253,10 @@ internal class JceOutputTest {
override
fun
writeTo
(
var1
:
JceOutputStream
)
{
var1
.
write
(
message
,
0
)
}
override
fun
toString
():
String
{
return
"TestMiraiStruct(message=$message)"
}
}
@Test
...
...
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