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
e129719d
Commit
e129719d
authored
Sep 05, 2019
by
Him188moe
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updated robot & network structure
parent
c353e8e8
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
450 additions
and
365 deletions
+450
-365
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
+68
-70
mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
.../main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
+359
-275
mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt
...c/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt
+1
-0
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
.../main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
+3
-12
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
...n/java/net/mamoe/mirai/network/packet/login/LoginState.kt
+3
-1
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java
+2
-3
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
+12
-2
No files found.
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
View file @
e129719d
...
...
@@ -10,7 +10,7 @@ class Group(robot: Robot, number: Long) : Contact(robot, number), Closeable {
val
members
=
ContactList
<
QQ
>()
override
fun
sendMessage
(
message
:
Message
)
{
robot
.
network
.
packetSystem
.
sendGroupMessage
(
this
,
message
)
robot
.
network
.
messageHandler
.
sendGroupMessage
(
this
,
message
)
}
override
fun
sendXMLMessage
(
message
:
String
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
View file @
e129719d
...
...
@@ -12,7 +12,7 @@ import net.mamoe.mirai.message.defaults.At
*/
class
QQ
(
robot
:
Robot
,
number
:
Long
)
:
Contact
(
robot
,
number
)
{
override
fun
sendMessage
(
message
:
Message
)
{
robot
.
network
.
packetSystem
.
sendFriendMessage
(
this
,
message
)
robot
.
network
.
messageHandler
.
sendFriendMessage
(
this
,
message
)
}
override
fun
sendXMLMessage
(
message
:
String
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
View file @
e129719d
...
...
@@ -7,9 +7,8 @@ import java.util.stream.Collectors
/**
* @author Him188moe
*/
interface
Protocol
{
companion
object
{
val
SERVER_IP
:
ArrayList
<
String
>
=
object
:
ArrayList
<
String
>()
{
object
Protocol
{
val
SERVER_IP
:
List
<
String
>
=
object
:
ArrayList
<
String
>()
{
init
{
add
(
"183.60.56.29"
)
...
...
@@ -25,7 +24,7 @@ interface Protocol {
}
}
get
()
=
Collections
.
unmodifiableList
(
field
)
const
val
head
=
"02"
const
val
ver
=
"37 13"
...
...
@@ -90,5 +89,4 @@ interface Protocol {
.
map
{
s
->
s
.
toUByte
(
16
)
}
.
collect
(
Collectors
.
toList
()).
toUByteArray
()
}
}
mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
View file @
e129719d
...
...
@@ -11,15 +11,15 @@ import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePack
import
net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.utils.ClientLoginStatus
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.getGTK
import
net.mamoe.mirai.utils.lazyEncode
import
net.mamoe.mirai.utils.*
import
java.io.Closeable
import
java.net.DatagramPacket
import
java.net.DatagramSocket
import
java.net.InetSocketAddress
import
java.util.*
import
java.util.concurrent.ScheduledFuture
import
java.util.concurrent.TimeUnit
import
kotlin.reflect.KClass
/**
* A RobotNetworkHandler is used to connect with Tencent servers.
...
...
@@ -28,150 +28,230 @@ import java.util.concurrent.TimeUnit
*/
@Suppress
(
"EXPERIMENTAL_API_USAGE"
)
//to simplify code
internal
class
RobotNetworkHandler
(
private
val
robot
:
Robot
)
:
Closeable
{
private
val
socketHandler
:
SocketHandler
=
SocketHandler
()
private
var
socket
:
DatagramSocket
=
DatagramSocket
((
15314
+
Math
.
random
()
*
100
).
toInt
())
val
debugHandler
=
DebugHandler
()
val
loginHandler
=
LoginHandler
()
val
messageHandler
=
MessageHandler
()
val
actionHandler
=
ActionHandler
()
private
var
serverIP
:
String
=
""
set
(
value
)
{
serverAddress
=
InetSocketAddress
(
value
,
8000
)
field
=
value
private
val
packetHandlers
:
Map
<
KClass
<
out
PacketHandler
>,
PacketHandler
>
=
mapOf
(
DebugHandler
::
class
to debug
Handler
,
LoginHandler
::
class
to login
Handler
,
MessageHandler
::
class
to message
Handler
,
ActionHandler
::
class
to action
Handler
)
restartSocket
()
}
private
lateinit
var
serverAddress
:
InetSocketAddress
private
var
closed
:
Boolean
=
false
private
lateinit
var
token00BA
:
ByteArray
//这些数据全部是login用的
private
lateinit
var
token0825
:
ByteArray
private
var
loginTime
:
Int
=
0
private
lateinit
var
loginIP
:
String
private
var
tgtgtKey
:
ByteArray
?
=
null
private
var
tlv0105
:
ByteArray
/**
* 0828_decr_key
*/
private
lateinit
var
sessionResponseDecryptionKey
:
ByteArray
private
var
verificationCodeSequence
:
Int
=
0
//这两个验证码使用
private
var
verificationCodeCache
:
ByteArray
?
=
null
//每次包只发一部分验证码来
private
var
verificationCodeCacheCount
:
Int
=
1
//
private
lateinit
var
verificationToken
:
ByteArray
private
lateinit
var
sessionKey
:
ByteArray
//这两个是登录成功后得到的
private
lateinit
var
sKey
:
String
/**
*
Used to access web API(for friends list etc.)
*
Not async
*/
private
lateinit
var
cookies
:
String
private
var
gtk
:
Int
=
0
private
var
ignoreMessage
:
Boolean
=
false
@ExperimentalUnsignedTypes
fun
sendPacket
(
packet
:
ClientPacket
)
{
socketHandler
.
sendPacket
(
packet
)
}
private
var
loginState
:
LoginState
?
=
null
set
(
value
)
{
field
=
value
if
(
value
!=
null
)
{
loginHook
?.
invoke
(
value
)
override
fun
close
()
{
this
.
packetHandlers
.
values
.
forEach
{
it
.
close
()
}
this
.
socketHandler
.
close
()
}
private
var
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
init
{
tlv0105
=
lazyEncode
{
it
.
writeHex
(
"01 05 00 30"
)
it
.
writeHex
(
"00 01 01 02 00 14 01 01 00 10"
)
it
.
writeRandom
(
16
)
it
.
writeHex
(
"00 14 01 02 00 10"
)
it
.
writeRandom
(
16
)
//private | internal
internal
fun
tryLogin
(
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
)
{
val
ipQueue
:
LinkedList
<
String
>
=
LinkedList
(
Protocol
.
SERVER_IP
)
fun
login
():
Boolean
{
val
ip
=
ipQueue
.
poll
()
return
if
(
ip
!=
null
)
{
this
@RobotNetworkHandler
.
socketHandler
.
touch
(
ip
)
{
state
->
if
(
state
==
LoginState
.
UNKNOWN
)
{
login
()
}
else
{
loginHook
?.
invoke
(
state
)
}
}
true
}
else
false
}
login
()
}
/**
* Try to login to server
*/
internal
fun
tryLogin
(
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
)
{
//"14.116.136.106",
tryLogin
()
@ExperimentalUnsignedTypes
internal
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
this
.
packetHandlers
.
values
.
forEach
{
it
.
onPacketReceived
(
packet
)
}
}
/**
* Try to login to server
*/
private
fun
tryLogin
(
serverAddress
:
String
,
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
)
{
touch
(
serverAddress
,
loginHook
)
private
inner
class
SocketHandler
:
Closeable
{
private
lateinit
var
socket
:
DatagramSocket
internal
var
serverIP
:
String
=
""
set
(
value
)
{
serverAddress
=
InetSocketAddress
(
value
,
8000
)
field
=
value
restartSocket
()
}
/**
* Start network
*/
private
fun
touch
(
serverAddress
:
String
,
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
)
{
serverIP
=
serverAddress
if
(
loginHook
!=
null
)
{
this
.
loginHook
=
loginHook
private
var
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
internal
var
loginState
:
LoginState
?
=
null
set
(
value
)
{
field
=
value
if
(
value
!=
null
&&
value
!=
LoginState
.
UNKNOWN
)
{
loginHook
?.
invoke
(
value
)
}
this
.
sendPacket
(
ClientTouchPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
serverIP
))
}
private
lateinit
var
serverAddress
:
InetSocketAddress
private
fun
restartSocket
()
{
socket
.
close
()
socket
=
DatagramSocket
((
15314
+
Math
.
random
()
*
100
).
toInt
())
socket
.
close
()
socket
.
connect
(
this
.
serverAddress
)
val
zeroByte
:
Byte
=
0
Thread
{
while
(
true
)
{
val
dp1
=
DatagramPacket
(
ByteArray
(
2048
),
2048
)
while
(
socket
.
isConnected
)
{
val
packet
=
DatagramPacket
(
ByteArray
(
2048
),
2048
)
kotlin
.
runCatching
{
socket
.
receive
(
packet
)
}
.
onSuccess
{
MiraiThreadPool
.
getInstance
().
submit
{
try
{
socket
.
receive
(
dp1
)
onPacketReceived
(
ServerPacket
.
ofByteArray
(
packet
.
data
.
removeZeroTail
())
)
}
catch
(
e
:
Exception
)
{
if
(
e
.
message
==
"socket closed"
)
{
e
.
printStackTrace
()
}
}
}.
onFailure
{
if
(
it
.
message
==
"socket closed"
)
{
if
(!
closed
)
{
restartSocket
()
}
return
@Thread
}
it
.
printStackTrace
()
}
MiraiThreadPool
.
getInstance
().
submit
{
var
i
=
dp1
.
data
.
size
-
1
while
(
dp1
.
data
[
i
]
==
zeroByte
)
{
--
i
}
}.
start
()
}
/**
* Start network and touch the server
*/
internal
fun
touch
(
serverAddress
:
String
,
loginHook
:
((
LoginState
)
->
Unit
)?
=
null
)
{
socketHandler
.
serverIP
=
serverAddress
if
(
loginHook
!=
null
)
{
this
.
loginHook
=
loginHook
}
sendPacket
(
ClientTouchPacket
(
robot
.
account
.
qqNumber
,
socketHandler
.
serverIP
))
}
/**
* Not async
*/
@ExperimentalUnsignedTypes
internal
fun
sendPacket
(
packet
:
ClientPacket
)
{
try
{
onPacketReceived
(
ServerPacket
.
ofByteArray
(
dp1
.
data
.
copyOfRange
(
0
,
i
+
1
)))
}
catch
(
e
:
Exception
)
{
packet
.
encode
()
packet
.
writeHex
(
Protocol
.
tail
)
val
data
=
packet
.
toByteArray
()
socket
.
send
(
DatagramPacket
(
data
,
data
.
size
))
MiraiLogger
info
"Packet sent: $packet"
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
}
override
fun
close
()
{
this
.
socket
.
close
()
this
.
loginState
=
null
this
.
loginHook
=
null
}
}.
start
()
}
@ExperimentalUnsignedTypes
internal
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
private
lateinit
var
sessionKey
:
ByteArray
abstract
inner
class
PacketHandler
:
Closeable
{
abstract
fun
onPacketReceived
(
packet
:
ServerPacket
)
override
fun
close
()
{
}
}
/**
* Kind of [PacketHandler] that prints all packets received in the format of hex byte array.
*/
inner
class
DebugHandler
:
PacketHandler
()
{
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
packet
.
decode
()
MiraiLogger
info
"Packet received: $packet"
if
(
packet
is
ServerEventPacket
)
{
sendPacket
(
ClientMessageResponsePacket
(
this
.
robot
.
account
.
qqNumber
,
packet
.
packetId
,
this
.
sessionKey
,
packet
.
eventIdentity
))
sendPacket
(
ClientMessageResponsePacket
(
robot
.
account
.
qqNumber
,
packet
.
packetId
,
sessionKey
,
packet
.
eventIdentity
))
}
}
}
/**
* 处理登录过程
*/
inner
class
LoginHandler
:
PacketHandler
()
{
private
lateinit
var
token00BA
:
ByteArray
private
lateinit
var
token0825
:
ByteArray
private
var
loginTime
:
Int
=
0
private
lateinit
var
loginIP
:
String
private
var
tgtgtKey
:
ByteArray
?
=
null
private
var
tlv0105
:
ByteArray
=
lazyEncode
{
it
.
writeHex
(
"01 05 00 30"
)
it
.
writeHex
(
"00 01 01 02 00 14 01 01 00 10"
)
it
.
writeRandom
(
16
)
it
.
writeHex
(
"00 14 01 02 00 10"
)
it
.
writeRandom
(
16
)
}
/**
* 0828_decr_key
*/
private
lateinit
var
sessionResponseDecryptionKey
:
ByteArray
private
var
verificationCodeSequence
:
Int
=
0
//这两个验证码使用
private
var
verificationCodeCache
:
ByteArray
?
=
null
//每次包只发一部分验证码来
private
var
verificationCodeCacheCount
:
Int
=
1
//
private
lateinit
var
verificationToken
:
ByteArray
private
var
heartbeatFuture
:
ScheduledFuture
<
*
>?
=
null
private
var
sKeyRefresherFuture
:
ScheduledFuture
<
*
>?
=
null
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerTouchResponsePacket
->
{
if
(
packet
.
serverIP
!=
null
)
{
//redirection
serverIP
=
packet
.
serverIP
!!
socketHandler
.
serverIP
=
packet
.
serverIP
!!
//connect(packet.serverIP!!)
sendPacket
(
ClientServerRedirectionPacket
(
packet
.
serverIP
!!
,
this
.
robot
.
account
.
qqNumber
))
sendPacket
(
ClientServerRedirectionPacket
(
packet
.
serverIP
!!
,
robot
.
account
.
qqNumber
))
}
else
{
//password submission
this
.
loginIP
=
packet
.
loginIP
this
.
loginTime
=
packet
.
loginTime
this
.
token0825
=
packet
.
token0825
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientPasswordSubmissionPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
robot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
packet
.
tgtgtKey
,
packet
.
token0825
))
sendPacket
(
ClientPasswordSubmissionPacket
(
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
packet
.
tgtgtKey
,
packet
.
token0825
))
}
}
is
ServerLoginResponseFailedPacket
->
{
this
.
loginState
=
packet
.
loginState
socketHandler
.
loginState
=
packet
.
loginState
MiraiLogger
error
"Login failed: "
+
packet
.
loginState
.
toString
()
return
}
...
...
@@ -181,18 +261,16 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
this
.
token00BA
=
packet
.
token00BA
this
.
verificationCodeCache
=
packet
.
verifyCodePart1
if
(
packet
.
unknownBoolean
!=
null
&&
packet
.
unknownBoolean
!!
)
{
this
.
verificationCodeSequence
=
1
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
1
,
this
.
robot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
verificationCodeSequence
,
this
.
token00BA
))
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
1
,
robot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
verificationCodeSequence
,
this
.
token00BA
))
}
}
is
ServerVerificationCodeRepeatPacket
->
{
//todo 这个名字正确么
this
.
tgtgtKey
=
packet
.
tgtgtKeyUpdate
this
.
token00BA
=
packet
.
token00BA
sendPacket
(
ClientLoginResendPacket3105
(
this
.
robot
.
account
.
qqNumber
,
this
.
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
this
.
token00BA
))
sendPacket
(
ClientLoginResendPacket3105
(
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
this
.
token00BA
))
}
is
ServerVerificationCodeTransmissionPacket
->
{
...
...
@@ -207,18 +285,17 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
//todo 看易语言 count 和 sequence 是怎样变化的
if
(
packet
.
transmissionCompleted
)
{
this
.
verificationCodeCache
TODO
(
"验证码好了"
)
}
else
{
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
this
.
verificationCodeCacheCount
,
this
.
robot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
verificationCodeSequence
,
this
.
token00BA
))
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
this
.
verificationCodeCacheCount
,
robot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
verificationCodeSequence
,
this
.
token00BA
))
}
}
is
ServerLoginResponseSuccessPacket
->
{
this
.
sessionResponseDecryptionKey
=
packet
.
sessionResponseDecryptionKey
sendPacket
(
ClientSessionRequestPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
serverIP
,
packet
.
token38
,
packet
.
token88
,
packet
.
encryptionKey
,
this
.
tlv0105
))
sendPacket
(
ClientSessionRequestPacket
(
robot
.
account
.
qqNumber
,
socketHandler
.
serverIP
,
packet
.
token38
,
packet
.
token88
,
packet
.
encryptionKey
,
this
.
tlv0105
))
}
//是ClientPasswordSubmissionPacket之后服务器回复的
...
...
@@ -230,8 +307,8 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
if
(
packet
.
flag
==
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
)
{
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientLoginResendPacket3104
(
this
.
robot
.
account
.
qqNumber
,
this
.
robot
.
account
.
password
,
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
...
...
@@ -244,8 +321,8 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
))
}
else
{
sendPacket
(
ClientLoginResendPacket3106
(
this
.
robot
.
account
.
qqNumber
,
this
.
robot
.
account
.
password
,
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
...
...
@@ -259,98 +336,113 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
}
}
is
ServerSessionKeyResponsePacket
->
{
this
.
sessionKey
=
packet
.
sessionKey
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientHeartbeatPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
sessionKey
))
sessionKey
=
packet
.
sessionKey
heartbeatFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientHeartbeatPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
},
90000
,
90000
,
TimeUnit
.
MILLISECONDS
)
RobotLoginSucceedEvent
(
robot
).
broadcast
()
//登录成功后会收到大量上次的消息, 忽略掉
MiraiThreadPool
.
getInstance
().
schedule
({
ignoreMessage
=
false
(
packetHandlers
[
MessageHandler
::
class
]
as
MessageHandler
).
ignoreMessage
=
false
},
2
,
TimeUnit
.
SECONDS
)
this
.
tlv0105
=
packet
.
tlv0105
sendPacket
(
ClientChangeOnlineStatusPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
sessionKey
,
ClientLoginStatus
.
ONLINE
))
sendPacket
(
ClientChangeOnlineStatusPacket
(
robot
.
account
.
qqNumber
,
sessionKey
,
ClientLoginStatus
.
ONLINE
))
}
is
ServerLoginSuccessPacket
->
{
loginState
=
LoginState
.
SUCCEED
sendPacket
(
ClientSKeyRequestPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
sessionKey
))
socketHandler
.
loginState
=
LoginState
.
SUCCEED
sendPacket
(
ClientSKeyRequestPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
}
is
ServerSKeyResponsePacket
->
{
this
.
sKey
=
packet
.
sKey
this
.
cookies
=
"uin=o"
+
this
.
robot
.
account
.
qqNumber
+
";skey="
+
this
.
sKey
+
";"
val
actionHandler
=
packetHandlers
[
ActionHandler
::
class
]
as
ActionHandler
actionHandler
.
sKey
=
packet
.
sKey
actionHandler
.
cookies
=
"uin=o"
+
robot
.
account
.
qqNumber
+
";skey="
+
actionHandler
.
sKey
+
";"
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
sessionKey
))
sKeyRefresherFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
},
1800000
,
1800000
,
TimeUnit
.
MILLISECONDS
)
this
.
gtk
=
getGTK
(
sKey
)
sendPacket
(
ClientAccountInfoRequestPacket
(
this
.
robot
.
account
.
qqNumber
,
this
.
sessionKey
))
actionHandler
.
gtk
=
getGTK
(
actionHandler
.
sKey
)
sendPacket
(
ClientAccountInfoRequestPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
}
is
ServerHeartbeatResponsePacket
->
{
is
ServerEventPacket
.
Raw
->
onPacketReceived
(
packet
.
distribute
())
}
is
ServerVerificationCodePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerLoginResponseResendPacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerSessionKeyResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionResponseDecryptionKey
))
is
ServerTouchResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerSKeyResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
sessionKey
))
is
ServerAccountInfoResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
sessionKey
))
is
ServerEventPacket
.
Raw
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
sessionKey
))
is
ServerAccountInfoResponsePacket
->
{
is
ServerAccountInfoResponsePacket
,
is
ServerHeartbeatResponsePacket
,
is
UnknownServerPacket
->
{
//ignored
}
else
->
{
is
ServerFriendMessageEventPacket
->
{
if
(
ignoreMessage
)
{
return
}
FriendMessageEvent
(
this
.
robot
,
this
.
robot
.
contacts
.
getQQ
(
packet
.
qq
),
packet
.
message
)
}
is
ServerGroupMessageEventPacket
->
{
//todo message chain
//GroupMessageEvent(this.robot, this.robot.contacts.getGroupByNumber(packet.groupNumber), this.robot.contacts.getQQ(packet.qq), packet.message)
}
is
UnknownServerEventPacket
->
{
//unknown message event
}
override
fun
close
()
{
this
.
verificationCodeCache
=
null
this
.
tgtgtKey
=
null
is
UnknownServerPacket
->
{
this
.
heartbeatFuture
?.
cancel
(
true
)
this
.
sKeyRefresherFuture
?.
cancel
(
true
)
this
.
heartbeatFuture
=
null
this
.
sKeyRefresherFuture
=
null
}
}
is
ServerGroupUploadFileEventPacket
->
{
/**
* 处理消息事件, 承担消息发送任务.
*/
inner
class
MessageHandler
:
PacketHandler
()
{
internal
var
ignoreMessage
:
Boolean
=
false
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerGroupUploadFileEventPacket
->
{
//todo
}
is
ServerEventPacket
.
Raw
->
onPacketReceived
(
packet
.
distribute
())
is
ServerFriendMessageEventPacket
->
{
if
(
ignoreMessage
)
{
return
}
is
ServerVerificationCodePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerLoginResponseResendPacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerSessionKeyResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionResponseDecryptionKey
))
is
ServerTouchResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerSKeyResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionKey
))
is
ServerAccountInfoResponsePacket
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionKey
))
is
ServerEventPacket
.
Raw
.
Encrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionKey
))
FriendMessageEvent
(
robot
,
robot
.
contacts
.
getQQ
(
packet
.
qq
),
packet
.
message
)
}
is
ServerGroupMessageEventPacket
->
{
//todo message chain
//GroupMessageEvent(this.robot, robot.contacts.getGroupByNumber(packet.groupNumber), robot.contacts.getQQ(packet.qq), packet.message)
}
is
UnknownServerEventPacket
,
is
ServerSendFriendMessageResponsePacket
,
is
ServerSendGroupMessageResponsePacket
->
{
//ignored
}
else
->
{
//ignored
}
else
->
throw
IllegalArgumentException
(
packet
.
toString
())
}
}
internal
val
packetSystem
:
PacketSystem
=
PacketSystem
()
inner
class
PacketSystem
{
fun
sendFriendMessage
(
qq
:
QQ
,
message
:
Message
)
{
TODO
()
//sendPacket(ClientSendFriendMessagePacket(robot.account.qqNumber, qq.number, sessionKey, message))
...
...
@@ -360,31 +452,23 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
TODO
()
//sendPacket(ClientSendGroupMessagePacket(group.groupId, robot.account.qqNumber, sessionKey, message))
}
}
/**
* Not async
* 动作: 获取好友列表, 点赞, 踢人等.
* 处理动作事件, 承担动作任务.
*/
@ExperimentalUnsignedTypes
fun
sendPacket
(
packet
:
ClientPacket
)
{
try
{
packet
.
encode
()
packet
.
writeHex
(
Protocol
.
tail
)
inner
class
ActionHandler
:
PacketHandler
()
{
internal
lateinit
var
cookies
:
String
internal
lateinit
var
sKey
:
String
internal
var
gtk
:
Int
=
0
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
val
data
=
packet
.
toByteArray
()
socket
.
send
(
DatagramPacket
(
data
,
data
.
size
))
MiraiLogger
info
"Packet sent: $packet"
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
}
override
fun
close
()
{
this
.
socket
.
close
()
this
.
loginState
=
null
this
.
loginHook
=
null
this
.
verificationCodeCache
=
null
this
.
tgtgtKey
=
null
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt
View file @
e129719d
...
...
@@ -17,6 +17,7 @@ class ClientAccountInfoRequestPacket(
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
View file @
e129719d
...
...
@@ -53,11 +53,13 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
551
,
487
->
LoginState
.
DEVICE_LOCK
359
->
LoginState
.
TAKEN_BACK
else
->
LoginState
.
UNKNOWN
/*
//unknown
63 -> throw IllegalArgumentException(bytes.size.toString() + " (Unknown error)")
351 -> throw IllegalArgumentException(bytes.size.toString() + " (Illegal package data or Unknown error)")//包数据有误
else
->
throw
IllegalArgumentException
(
bytes
.
size
.
toString
())
else -> throw IllegalArgumentException(bytes.size.toString())
*/
},
stream
)
}
...
...
@@ -112,17 +114,6 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
fun
DataInputStream
.
readUntil
(
byte
:
Byte
):
ByteArray
{
var
buff
=
byteArrayOf
()
var
b
:
Byte
b
=
readByte
()
while
(
b
!=
byte
)
{
buff
+=
b
b
=
readByte
()
}
return
buff
}
@ExperimentalUnsignedTypes
fun
DataInputStream
.
readIP
():
String
{
var
buff
=
""
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
View file @
e129719d
...
...
@@ -14,5 +14,7 @@ enum class LoginState {
DEVICE_LOCK
,
//设备锁
TAKEN_BACK
,
//被回收
// VERIFICATION_CODE,//需要验证码
// SUCCEED,
UNKNOWN
,
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java
View file @
e129719d
...
...
@@ -11,9 +11,8 @@ import java.util.Random;
* @author iweiz https://github.com/iweizime/StepChanger/blob/master/app/src/main/java/me/iweizi/stepchanger/qq/Cryptor.java
*/
public
final
class
TEA
{
public
static
final
TEA
CRYPTOR_SHARE_KEY
=
new
TEA
(
Protocol
.
Companion
.
hexToBytes
(
Protocol
.
shareKey
));
public
static
final
TEA
CRYPTOR_0825KEY
=
new
TEA
(
Protocol
.
Companion
.
hexToBytes
(
Protocol
.
key0825
));
public
static
final
TEA
CRYPTOR_00BAKEY
=
new
TEA
(
Protocol
.
Companion
.
hexToBytes
(
Protocol
.
key00BA
));
public
static
final
TEA
CRYPTOR_SHARE_KEY
=
new
TEA
(
Protocol
.
INSTANCE
.
hexToBytes
(
Protocol
.
shareKey
));
public
static
final
TEA
CRYPTOR_0825KEY
=
new
TEA
(
Protocol
.
INSTANCE
.
hexToBytes
(
Protocol
.
key0825
));
private
static
final
long
UINT32_MASK
=
0xffffffff
L
;
private
final
long
[]
mKey
;
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
View file @
e129719d
...
...
@@ -79,7 +79,7 @@ operator fun File.plus(child: String): File = File(this, child)
private
const
val
GTK_BASE_VALUE
:
Int
=
5381
fun
getGTK
(
sKey
:
String
):
Int
{
internal
fun
getGTK
(
sKey
:
String
):
Int
{
var
value
=
GTK_BASE_VALUE
for
(
c
in
sKey
.
toCharArray
())
{
value
+=
(
value
shl
5
)
+
c
.
toInt
()
...
...
@@ -89,7 +89,7 @@ fun getGTK(sKey: String): Int {
return
value
}
fun
getCrc32
(
key
:
ByteArray
):
Int
=
CRC32
().
let
{
it
.
update
(
key
);
it
.
value
.
toInt
()
}
internal
fun
getCrc32
(
key
:
ByteArray
):
Int
=
CRC32
().
let
{
it
.
update
(
key
);
it
.
value
.
toInt
()
}
/**
...
...
@@ -122,3 +122,13 @@ fun Any.getAllDeclaredFields(): List<Field> {
return
list
}
private
const
val
ZERO_BYTE
:
Byte
=
0
fun
ByteArray
.
removeZeroTail
():
ByteArray
{
var
i
=
this
.
size
-
1
while
(
this
[
i
]
==
ZERO_BYTE
)
{
--
i
}
return
this
.
copyOfRange
(
0
,
i
+
1
)
}
\ No newline at end of file
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