Commit cf052614 authored by Him188's avatar Him188

Use Klock

parent 244996ac
...@@ -19,6 +19,7 @@ allprojects { ...@@ -19,6 +19,7 @@ allprojects {
version = "1.0" version = "1.0"
repositories { repositories {
jcenter()//klock
google() google()
maven { url "https://mirrors.huaweicloud.com/repository/maven/" } maven { url "https://mirrors.huaweicloud.com/repository/maven/" }
} }
......
...@@ -30,4 +30,5 @@ ext { ...@@ -30,4 +30,5 @@ ext {
kotlinxIOJS = "org.jetbrains.kotlinx:kotlinx-io-js:$kotlinx_io_version" kotlinxIOJS = "org.jetbrains.kotlinx:kotlinx-io-js:$kotlinx_io_version"
kotlinxIONative = "org.jetbrains.kotlinx:kotlinx-io-native:$kotlinx_io_version" kotlinxIONative = "org.jetbrains.kotlinx:kotlinx-io-native:$kotlinx_io_version"
klock = "com.soywiz.korlibs.klock:klock:1.7.0"
} }
...@@ -35,6 +35,7 @@ kotlin { ...@@ -35,6 +35,7 @@ kotlin {
implementation rootProject.ext.atomicFUCommon implementation rootProject.ext.atomicFUCommon
implementation rootProject.ext.kotlinxIOCommon implementation rootProject.ext.kotlinxIOCommon
implementation rootProject.ext.klock
} }
} }
...@@ -51,6 +52,7 @@ kotlin { ...@@ -51,6 +52,7 @@ kotlin {
implementation 'org.yaml:snakeyaml:1.18' implementation 'org.yaml:snakeyaml:1.18'
implementation 'org.jsoup:jsoup:1.12.1' implementation 'org.jsoup:jsoup:1.12.1'
implementation 'org.ini4j:ini4j:0.5.2' implementation 'org.ini4j:ini4j:0.5.2'
implementation rootProject.ext.klock
} }
} }
......
...@@ -14,8 +14,6 @@ import net.mamoe.mirai.utils.toUHexString ...@@ -14,8 +14,6 @@ import net.mamoe.mirai.utils.toUHexString
/** /**
* The mirror of functions in inner classes of [Bot] * The mirror of functions in inner classes of [Bot]
*
* @author Him188moe
*/ */
//Contacts //Contacts
......
...@@ -147,7 +147,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -147,7 +147,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
val expect = expectPacket<ServerTouchResponsePacket>() val expect = expectPacket<ServerTouchResponsePacket>()
NetworkScope.launch { processReceive() } NetworkScope.launch { processReceive() }
NetworkScope.launch { NetworkScope.launch {
if (withTimeoutOrNull(configuration.touchTimeoutMillis) { expect.join() } == null) { if (withTimeoutOrNull(configuration.touchTimeout.millisecondsLong) { expect.join() } == null) {
loginResult.complete(LoginResult.TIMEOUT) loginResult.complete(LoginResult.TIMEOUT)
} }
} }
...@@ -342,7 +342,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -342,7 +342,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
this.token00BA = packet.token00BA this.token00BA = packet.token00BA
this.captchaCache = packet.captchaPart1 this.captchaCache = packet.captchaPart1
if (packet.unknownBoolean == true) { if (packet.unknownBoolean) {
this.captchaSectionId = 1 this.captchaSectionId = 1
socket.sendPacket(ClientCaptchaTransmissionRequestPacket(bot.qqAccount, this.token0825, this.captchaSectionId++, packet.token00BA)) socket.sendPacket(ClientCaptchaTransmissionRequestPacket(bot.qqAccount, this.token0825, this.captchaSectionId++, packet.token00BA))
} }
...@@ -403,11 +403,11 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -403,11 +403,11 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
heartbeatJob = NetworkScope.launch { heartbeatJob = NetworkScope.launch {
while (socket.isOpen) { while (socket.isOpen) {
delay(configuration.heartbeatPeriodMillis) delay(configuration.heartbeatPeriod.millisecondsLong)
with(session) { with(session) {
class HeartbeatTimeoutException : CancellationException("heartbeat timeout") class HeartbeatTimeoutException : CancellationException("heartbeat timeout")
if (withTimeoutOrNull(configuration.heartbeatTimeoutMillis) { if (withTimeoutOrNull(configuration.heartbeatTimeout.millisecondsLong) {
ClientHeartbeatPacket(bot.qqAccount, sessionKey).sendAndExpect<ServerHeartbeatResponsePacket> {} ClientHeartbeatPacket(bot.qqAccount, sessionKey).sendAndExpect<ServerHeartbeatResponsePacket> {}
} == null) { } == null) {
bot.logPurple("Heartbeat timed out") bot.logPurple("Heartbeat timed out")
......
...@@ -20,7 +20,7 @@ object TIMProtocol { ...@@ -20,7 +20,7 @@ object TIMProtocol {
).forEach { list.add(solveIpAddress(it)) } ).forEach { list.add(solveIpAddress(it)) }
list.toList() list.toList()
}() }()//不使用lazy是为了在启动时就加载.
const val head = "02" const val head = "02"
const val ver = "37 13" const val ver = "37 13"
...@@ -36,6 +36,9 @@ object TIMProtocol { ...@@ -36,6 +36,9 @@ object TIMProtocol {
const val constantData1 = "00 18 00 16 00 01 " const val constantData1 = "00 18 00 16 00 01 "
const val constantData2 = "00 00 04 53 00 00 00 01 00 00 15 85 " const val constantData2 = "00 00 04 53 00 00 00 01 00 00 15 85 "
//todo 使用 byte array
/** /**
* Touch 发出时写入, 并用于加密, 接受 sendTouch response 时解密. * Touch 发出时写入, 并用于加密, 接受 sendTouch response 时解密.
*/ */
......
...@@ -22,22 +22,23 @@ class ClientPasswordSubmissionPacket constructor( ...@@ -22,22 +22,23 @@ class ClientPasswordSubmissionPacket constructor(
private val loginIP: String, private val loginIP: String,
private val privateKey: ByteArray, private val privateKey: ByteArray,
private val token0825: ByteArray, private val token0825: ByteArray,
private val token00BA: ByteArray? = null,// private val token00BA: ByteArray? = null,
private val randomDeviceName: Boolean = false, private val randomDeviceName: Boolean = false,
private val tlv0006: IoBuffer? = null private val tlv0006: IoBuffer? = null
) : ClientPacket() { ) : ClientPacket() {
override fun encode(builder: BytePacketBuilder) = with(builder) { override fun encode(builder: BytePacketBuilder) = with(builder) {
this.writeQQ(bot) writeQQ(bot)
this.writeHex(TIMProtocol.passwordSubmissionTLV1) writeHex(TIMProtocol.passwordSubmissionTLV1)
this.writeShort(25) writeShort(25)
this.writeHex(TIMProtocol.publicKey)//25 writeHex(TIMProtocol.publicKey)//=25
this.writeHex("00 00 00 10")//=16 writeZero(2)
this.writeHex(TIMProtocol.key0836)//16 writeShort(16)
writeHex(TIMProtocol.key0836)//=16
//TODO shareKey 极大可能为 publicKey, key0836 计算得到 //TODO shareKey 极大可能为 publicKey, key0836 计算得到
this.encryptAndWrite(TIMProtocol.shareKey.hexToBytes()) { encryptAndWrite(TIMProtocol.shareKey) {
writePart1(bot, password, loginTime, loginIP, privateKey, token0825, randomDeviceName, tlv0006) writePart1(bot, password, loginTime, loginIP, privateKey, token0825, randomDeviceName, tlv0006)
if (token00BA != null) { if (token00BA != null) {
......
...@@ -127,7 +127,7 @@ class ServerLoginResponseCaptchaInitPacket(input: ByteReadPacket) : ServerLoginR ...@@ -127,7 +127,7 @@ class ServerLoginResponseCaptchaInitPacket(input: ByteReadPacket) : ServerLoginR
lateinit var captchaPart1: IoBuffer lateinit var captchaPart1: IoBuffer
lateinit var token00BA: ByteArray lateinit var token00BA: ByteArray
var unknownBoolean: Boolean? = null var unknownBoolean: Boolean by Delegates.notNull()
@Tested @Tested
......
package net.mamoe.mirai.utils package net.mamoe.mirai.utils
import com.soywiz.klock.TimeSpan
import com.soywiz.klock.seconds
import net.mamoe.mirai.network.protocol.tim.packet.login.ServerTouchResponsePacket import net.mamoe.mirai.network.protocol.tim.packet.login.ServerTouchResponsePacket
/** /**
...@@ -9,7 +11,7 @@ class BotNetworkConfiguration { ...@@ -9,7 +11,7 @@ class BotNetworkConfiguration {
/** /**
* 等待 [ServerTouchResponsePacket] 的时间 * 等待 [ServerTouchResponsePacket] 的时间
*/ */
var touchTimeoutMillis: Long = 2000 var touchTimeout: TimeSpan = 2.seconds
/** /**
* 是否使用随机的设备名. * 是否使用随机的设备名.
...@@ -21,13 +23,13 @@ class BotNetworkConfiguration { ...@@ -21,13 +23,13 @@ class BotNetworkConfiguration {
/** /**
* 心跳周期. 过长会导致被服务器断开连接. * 心跳周期. 过长会导致被服务器断开连接.
*/ */
var heartbeatPeriodMillis: Long = 1 * 60 * 1000 var heartbeatPeriod: TimeSpan = 60.seconds
/** /**
* 每次心跳时等待结果的时间. * 每次心跳时等待结果的时间.
* 一旦心跳超时, 整个网络服务将会重启 (将消耗约 1s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响. * 一旦心跳超时, 整个网络服务将会重启 (将消耗约 1s). 除正在进行的任务 (如图片上传) 会被中断外, 事件和插件均不受影响.
*/ */
var heartbeatTimeoutMillis: Long = 2000 var heartbeatTimeout: TimeSpan = 2.seconds
companion object { companion object {
val Default = BotNetworkConfiguration() val Default = BotNetworkConfiguration()
......
package net.mamoe.mirai.utils package net.mamoe.mirai.utils
import com.soywiz.klock.DateTime
/** /**
* 时间戳 * 时间戳
*/ */
expect val currentTime: Long val currentTime: Long = DateTime.nowUnixLong()
/** /**
* 设备名 * 设备名
......
...@@ -41,13 +41,22 @@ fun UInt.toByteArray(): ByteArray = byteArrayOf( ...@@ -41,13 +41,22 @@ fun UInt.toByteArray(): ByteArray = byteArrayOf(
fun Int.toUHexString(separator: String = " "): String = this.toByteArray().toUHexString(separator) fun Int.toUHexString(separator: String = " "): String = this.toByteArray().toUHexString(separator)
fun Byte.toUHexString(): String = this.toUByte().toString(16).toUpperCase() fun Byte.toUHexString(): String = this.toUByte().toString(16).toUpperCase()
fun String.hexToBytes(): ByteArray = HexCache.hexToBytes(this) fun String.hexToBytes(): ByteArray = HexCache.hexToBytes(this)
/**
* 将 Hex 转为 UByteArray, 有根据 hex 的 [hashCode] 建立的缓存.
*/
fun String.hexToUBytes(): UByteArray = HexCache.hexToUBytes(this) fun String.hexToUBytes(): UByteArray = HexCache.hexToUBytes(this)
fun String.hexToInt(): Int = hexToBytes().toUInt().toInt() fun String.hexToInt(): Int = hexToBytes().toUInt().toInt()
fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() } fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() }
fun ByteArray.toUInt(): UInt = this[0].toUInt().and(255u).shl(24) + this[1].toUInt().and(255u).shl(16) + this[2].toUInt().and(255u).shl(8) + this[3].toUInt().and(255u).shl(0) fun ByteArray.toUInt(): UInt = this[0].toUInt().and(255u).shl(24) + this[1].toUInt().and(255u).shl(16) + this[2].toUInt().and(255u).shl(8) + this[3].toUInt().and(255u).shl(0)
fun ByteArray.toIoBuffer(): IoBuffer = IoBuffer.Pool.borrow().let { it.writeFully(this); it } fun ByteArray.toIoBuffer(): IoBuffer = IoBuffer.Pool.borrow().let { it.writeFully(this); it }
/**
* Hex 转换 [ByteArray] 和 [UByteArray] 缓存.
* 为 [net.mamoe.mirai.network.protocol.tim.TIMProtocol] 的 hex 常量使用
*/
internal object HexCache { internal object HexCache {
private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf() private val hexToByteArrayCacheMap: MutableMap<Int, ByteArray> = mutableMapOf()
......
...@@ -8,8 +8,6 @@ import java.net.InetAddress ...@@ -8,8 +8,6 @@ import java.net.InetAddress
import java.security.MessageDigest import java.security.MessageDigest
import java.util.zip.CRC32 import java.util.zip.CRC32
actual val currentTime: Long = System.currentTimeMillis()
actual val deviceName: String = InetAddress.getLocalHost().hostName actual val deviceName: String = InetAddress.getLocalHost().hostName
......
...@@ -5,9 +5,9 @@ dependencies { ...@@ -5,9 +5,9 @@ dependencies {
implementation project(':mirai-core') implementation project(':mirai-core')
compile files('./lib/jpcap.jar') compile files('./lib/jpcap.jar')
compile rootProject.ext.coroutineCommon implementation rootProject.ext.coroutineCommon
compile rootProject.ext.kotlinJvm implementation rootProject.ext.kotlinJvm
compile rootProject.ext.kotlinxIOJvm implementation rootProject.ext.kotlinxIOJvm
} }
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
......
...@@ -23,32 +23,11 @@ object Main { ...@@ -23,32 +23,11 @@ object Main {
@JvmStatic @JvmStatic
fun main(args: Array<String>) { fun main(args: Array<String>) {
/*-------------- 第一步绑定网络设备 --------------*/
val devices = JpcapCaptor.getDeviceList() val devices = JpcapCaptor.getDeviceList()
/*
\Device\NPF_{0E7103E4-BF96-4B66-A23B-F6F630D814CD} | Microsoft
\Device\NPF_{2CCA31E2-93D5-42F2-92C1-5882E18A8E95} | VMware Virtual Ethernet Adapter
\Device\NPF_{A12C8971-858B-4BC8-816C-4077E1636AC5} | VMware Virtual Ethernet Adapter
\Device\NPF_{231C4E27-AF20-4362-BCA3-107236CB8A2E} | MS NDIS 6.0 LoopBack Driver
\Device\NPF_{500B5537-AA10-4E2F-8F7D-E6BD365BDCD1} | Microsoft
\Device\NPF_{A177317B-903A-45B5-8AEA-3698E423ABD6} | Microsoft
*/
/*
for (n in devices) {
println(n.name + " | " + n.description)
}
println("-------------------------------------------")
exitProcess(0)*/
val jpcap: JpcapCaptor? val jpcap: JpcapCaptor?
val caplen = 4096 val caplen = 4096
val promiscCheck = true val promiscCheck = true
jpcap = JpcapCaptor.openDevice(devices[0], caplen, promiscCheck, 50) jpcap = JpcapCaptor.openDevice(devices[0], caplen, promiscCheck, 50)
/*----------第二步抓包-----------------*/
while (true) { while (true) {
assert(jpcap != null) assert(jpcap != null)
val pk = jpcap!!.packet val pk = jpcap!!.packet
...@@ -60,7 +39,11 @@ object Main { ...@@ -60,7 +39,11 @@ object Main {
} }
if (localIp in pk.dst_ip.hostAddress) {//接受 if (localIp in pk.dst_ip.hostAddress) {//接受
try {
dataReceived(pk.data) dataReceived(pk.data)
} catch (e: Exception) {
e.printStackTrace()
}
} else { } else {
try { try {
dataSent(pk.data) dataSent(pk.data)
...@@ -88,7 +71,7 @@ object Main { ...@@ -88,7 +71,7 @@ object Main {
* 6. 运行到 `mov eax,dword ptr ss:[ebp+10]` * 6. 运行到 `mov eax,dword ptr ss:[ebp+10]`
* 7. 查看内存, 从 `eax` 开始的 16 bytes 便是 `sessionKey` * 7. 查看内存, 从 `eax` 开始的 16 bytes 便是 `sessionKey`
*/ */
val sessionKey: ByteArray = "F1 68 24 ED A8 6D 33 6E 5C B7 E0 F4 45 77 21 04".hexToBytes() val sessionKey: ByteArray = "99 91 B9 8B 79 45 FD CF 51 4A B9 DE 14 61 ED E3".hexToBytes()
fun dataReceived(data: ByteArray) { fun dataReceived(data: ByteArray) {
println("--------------") println("--------------")
......
...@@ -24,7 +24,6 @@ suspend fun main() { ...@@ -24,7 +24,6 @@ suspend fun main() {
), Console()) ), Console())
bot.login { bot.login {
touchTimeoutMillis = 2000
randomDeviceName = true randomDeviceName = true
}.let { }.let {
if (it != LoginResult.SUCCESS) { if (it != LoginResult.SUCCESS) {
......
...@@ -6,3 +6,5 @@ include(':mirai-demos:mirai-demo-1') ...@@ -6,3 +6,5 @@ include(':mirai-demos:mirai-demo-1')
include(':mirai-demos') include(':mirai-demos')
include(':mirai-debug') include(':mirai-debug')
project(':mirai-demos:mirai-demo-1').projectDir = file('mirai-demos/mirai-demo-1') project(':mirai-demos:mirai-demo-1').projectDir = file('mirai-demos/mirai-demo-1')
enableFeaturePreview('GRADLE_METADATA')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment