mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-07 16:40:43 +08:00
Merge remote-tracking branch 'origin/master'
# Conflicts: # mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
This commit is contained in:
commit
e7c49eb471
5
.gitignore
vendored
5
.gitignore
vendored
@ -28,4 +28,7 @@ hs_err_pid*
|
||||
mirai.iml
|
||||
/.idea/
|
||||
.idea/*
|
||||
/.idea/*
|
||||
/.idea/*
|
||||
|
||||
test/
|
||||
/test
|
@ -2,16 +2,16 @@
|
||||
|
||||
## Get_tlv_0006
|
||||
|
||||
C 构建包
|
||||
C 构建包, 近 C 使用
|
||||
|
||||
### Var
|
||||
#### Var
|
||||
type | var name | value/from
|
||||
---- | ---|---
|
||||
?bytes | MD51 | md5(raw password)
|
||||
?bytes | MD51 | md5(raw password)
|
||||
?bytes | MD52 | md5((MD51 + “ 00 00 00 00 ” + g_QQ).hextobytes())
|
||||
4bytes |m_loginIP | 服务器提供(Dispose_0825)
|
||||
16bytes| m_tgtgtKey| random
|
||||
### Packet data
|
||||
4bytes |m_loginIP | 服务器提供(Dispose_0825)
|
||||
16bytes| m_tgtgtKey| |
|
||||
#### Packet data
|
||||
|
||||
type | value
|
||||
---- | ---
|
||||
|
@ -14,7 +14,7 @@ C: 发送登录`08 25 31 01`
|
||||
|
||||
S: 回复`08 25 31 01`(ID与C发送的相同), 告诉C是否需 redirect
|
||||
|
||||
**Redirection**
|
||||
**[Redirection](Redirection.md)**
|
||||
|
||||
如果需要 redirect
|
||||
C: 发送 redirect 包`08 25 31 02`到新的服务器
|
||||
@ -46,10 +46,21 @@ S: 发送 `08 36 31 03` 告知登录结果.
|
||||
- g_clientKey
|
||||
- token38
|
||||
- token88
|
||||
- encryptionKey
|
||||
- encryptionKey
|
||||
|
||||
若不成功, 理由:
|
||||
- 需要验证码:
|
||||
//todo
|
||||
- 密码错误
|
||||
- 未知(重新登录)
|
||||
- 冻结
|
||||
- 账号不存在
|
||||
- 设备锁
|
||||
- 被回收
|
||||
|
||||
C: 回复 `08 28 04 34`
|
||||
Sample
|
||||
Sample
|
||||
|
||||
```text
|
||||
02 37 13 08 28 04 34 76 E4 B8 DD 02 00 00 00 01 2E 01 00 00 68 52 00 30 00 3A 00 38 BA 24 BF EA 76 94 2C 9B 91 A8 8F 0E 7C EC F5 41 77 3C B9 D4 95 50 F2 00 FD CB E3 48 36 FB 89 13 CE E4 EA 76 A2 2F 20 86 F6 0F E0 54 55 6E D4 0B 9B EA 07 6B E1 D4 87 56 F9 99 8F FA 12 8E 22 A6 5A 9D A6 DC C9 B6 5C 5A EC BE BF CC 38 BD E1 5A 23 21 CE 02 31 F1 E1 BD FB 8E 4D E9 59 E6 BB FB B2 36 0C 47 0A C0 F7 94 63 C3 2F AB 6E AE 00 01 1F 5F 60 8E B5 79 97 EB 10 59 A0 29 B3 3B 9C BA 5D 33 C4 2A 57 CA CF 94 7A 2D DD F7 B3 9C BC 65 5D D5 62 53 A8 1D D2 F1 5B DD D7 24 32 63 60 60 DD 33 1F 3A C0 71 38 86 BC 78 D3 7C 7A E1 97 71 AB B7 59 AD 27 32 D5 AF F3 DC 1B 7B 70 3B 08 C0 91 D8 BC F1 C4 DA E3 DA 86 A1 27 8A EE C3 5F D6 25 42 A0 CB 19 7F 08 80 F8 65 2C 27 31 B7 D4 85 C3 49 BD 99 48 FE A9 63 78 6D 18 C3 4E BB F7 8A C4 80 8C 8A 17 EB 47 AF 2A 12 73 71 08 A6 E7 C3 08 2B 9A 6F 8A C2 6C 3B 1A CF 05 D8 57 63 33 AC BD 45 98 C1 85 56 08 0F 9F 36 FD 60 69 BC D0 94 1A 11 4D C6 3E 78 1D F1 67 D2 1D C4 C8 17 2F DC F4 B6 4F 5F F5 EE 8B 73 68 AA 3B BA C6 94 C8 21 1E 95 6D C2 7A BE 8B 1D 92 21 8D 2C D8 B6 86 D1 30 BB 72 34 B9 A0 D2 2E 4C 98 3C 17 E2 B2 6A AD 75 E8 B0 DE F4 1A 6F 15 93 47 B3 4D DA 6F BE A3 47 D3 9B 58 2D 4B A3 76 0E 39 ED A5 C3 0A 34 BA 78 01 AE 20 A3 38 CE BA CD F6 D7 1B C9 E7 4C 83 6E 31 34 25 16 64 BA EE 4B 8D E7 0E 2F C8 08 72 50 AE 91 16 7F 68 14 60 7E D8 3F CC 26 2D F6 BC 65 72 C8 F4 EA 55 E6 1B E0 BF F4 9F 9C FD A9 93 B6 62 78 F0 A1 19 D2 87 6E B8 B7 E3 70 13 09 95 29 C9 05 EC 99 36 5C 96 47 C1 C4 06 5C 23 5C A3 AD B0 39 BC 70 75 3D AA E9 16 03 0E 62 1B D0 78 EA F2 5C FD 9C 04 D9 AB 75 00 F8 37 F1 A8 DD 7B 65 91 D3 58 DE C5 BA 9E AC 13 DE 35 BA 17 DC D1 AB A5 96 C4 99 81 8E 21 4B 2F C1 9B 4C E1 56 A7 5D AC 26 71 EC 49 F0 A6 B1 F5 43 EA AC BE E6 9F A0 C2 E1 68 35 97 7B 81 76 AF 9E BD BC A7 D8 9E FC C0 E8 21 B0 BA 20 6A D0 BD E7 00 59 06 61 A1 DF AA 9F BA F4 5D A6 7B 5B A1 D8 6B B5 E9 72 66 51 8A D3 CE 51 A9 08 C7 11 4B FB 29 2E 6C 48 5B 8A 50 C6 5D 3A C1 9E A1 51 B6 56 DD 6B F5 D2 FD AE AB A4 4A A8 1F 99 BA 7D 4F 62 D7 64 22 31 04 62 36 62 65 96 B3 5A 35 03
|
||||
```
|
||||
|
23
document/protocol/Password Verified.md
Normal file
23
document/protocol/Password Verified.md
Normal file
@ -0,0 +1,23 @@
|
||||
# TIM Protocol
|
||||
|
||||
## Password Verified
|
||||
|
||||
### S -> `08 25 31 02`(may be another)
|
||||
|
||||
#### Var
|
||||
type | var name | value/from
|
||||
---- | ---|---
|
||||
int |g_qq | qq number
|
||||
16bytes | tgtgtKey | |
|
||||
|
||||
#### Decryption
|
||||
|
||||
//todo
|
||||
|
||||
#### Packet data - Requiring
|
||||
|
||||
//todo
|
||||
|
||||
#### Packet data - Not Requiring
|
||||
|
||||
//todo
|
@ -1,19 +0,0 @@
|
||||
# TIM Protocol
|
||||
|
||||
## Redirection
|
||||
|
||||
S -> C
|
||||
|
||||
### Var
|
||||
type | var name | value/from
|
||||
---- | ---|---
|
||||
int |g_qq | qq number
|
||||
int| g_server| server ip
|
||||
### Packet data
|
||||
|
||||
skip 14
|
||||
if (flag == "08 25 31 02")
|
||||
data = decrypt (read 14..length-1, #redirectionKey)
|
||||
else
|
||||
data = decrypt (read 14..length-1, #_0825key)
|
||||
|
124
document/protocol/Redirection.md
Normal file
124
document/protocol/Redirection.md
Normal file
@ -0,0 +1,124 @@
|
||||
# TIM Protocol
|
||||
|
||||
## Redirection
|
||||
|
||||
### S -> `08 25 31 02`(may be another)
|
||||
|
||||
#### Decryption
|
||||
|
||||
skip 14 bytes
|
||||
if (flag == "08 25 31 02")
|
||||
data = decrypt (read bytes 14..length-1, #redirectionKey)
|
||||
else data = decrypt (read bytes 14..length-1, #_0825key)
|
||||
|
||||
#### Packet data - Requiring
|
||||
|
||||
**read byte == 0xFE**
|
||||
skip 94 bytes
|
||||
String serverIp = read 4 bytes and join them with separator "."
|
||||
|
||||
#### Packet data - Not Requiring
|
||||
|
||||
**read byte == 0x00**
|
||||
skip 4 bytes
|
||||
56bytes token0825 = read 56 bytes
|
||||
skip 6 bytes
|
||||
int loginTime = read int
|
||||
skip 1 byte
|
||||
String loginIP = read 4 bytes and join them with separator "."
|
||||
16bytes tgtgtKey = random 16 bytes
|
||||
|
||||
### C -> S - Requiring `08 25 31 02`
|
||||
|
||||
#### Var
|
||||
|
||||
type | var name | value/from
|
||||
---- | ---|---
|
||||
int | qq | |
|
||||
String | server ip | from redirection packet
|
||||
|
||||
#### Packet data
|
||||
|
||||
type | value
|
||||
---- | ---
|
||||
hex |#head
|
||||
hex |#ver
|
||||
hex |08 25 31 02
|
||||
int |qq
|
||||
hex |#fixver
|
||||
hex |#redirectionKey
|
||||
bytes |[TEA encrypted data](#tea-encrypted-data)
|
||||
|
||||
##### TEA encrypted data
|
||||
Key : #redirectionKey
|
||||
|
||||
type | value
|
||||
---- | ---
|
||||
hex |#_0825data0
|
||||
hex |#_0825data2
|
||||
int |qq
|
||||
hex |00 01 00 00 03 09 00 0C 00 01
|
||||
4bytes |g_server(split with "." and convert to byte)
|
||||
hex |01 6F A1 58 22 01 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 03 00 19
|
||||
hex | #publicKey
|
||||
|
||||
#### Note
|
||||
|
||||
Send the packet to new server via port 8000
|
||||
|
||||
|
||||
### C -> S - Not Requiring(Submitting password) `08 36 31 03`
|
||||
|
||||
#### Var
|
||||
|
||||
type | var name | value/from
|
||||
---- | ---|---
|
||||
int | qq | |
|
||||
String | password | |
|
||||
String | device name | UTF8 encoding. Sample: DESKTOP-M19QRYU
|
||||
16bytes | tgtgtKey | |
|
||||
bytes | MD5_1 | md5(password)
|
||||
bytes | MD5_2 | md5(MD5_1 + bytes{0, 0, 0, 0}} + qq.tobytes)
|
||||
|
||||
#### Packet data
|
||||
|
||||
type | value
|
||||
---- | ---
|
||||
hex |#head
|
||||
hex |#ver
|
||||
hex |08 36 31 03
|
||||
int |qq
|
||||
hex |03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19
|
||||
hex |#publicKey
|
||||
hex | 00 00 00 10
|
||||
hex | EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA
|
||||
bytes |[TEA encrypted data](#tea-encrypted--data)
|
||||
|
||||
##### TEA encrypted data
|
||||
Key : #shareKey
|
||||
|
||||
type | value
|
||||
---- | ---
|
||||
hex |01 12
|
||||
hex |00 38
|
||||
int |token0825(from [Packet data - Not Requiring](#packet-data---not-requiring))
|
||||
hex |03 0F
|
||||
int | device name length + 2
|
||||
int | device name length
|
||||
bytes | device name
|
||||
hex | 00 05 00 06 00 02
|
||||
int | qq
|
||||
hex | 00 06 00 78
|
||||
bytes | [TLV0006](Get_tlv_0006.md) Using md5 that you just calculated in
|
||||
hex | fix = 00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B
|
||||
hex | 00 1A 00 40
|
||||
bytes | TEAEncrypt(fix, tgtgtKey)
|
||||
hex | #_0825data0
|
||||
hex | #_0825data2
|
||||
int | qq
|
||||
hex | 00 00 00 00
|
||||
hex | 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 03 12 00 05 01 00 00 00 01 05 08 00 05 01 00 00 00 00 03 13 00 19 01 01 02 00 10 04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA
|
||||
hex | 00 00 00 00
|
||||
hex | 01 02 00 62 00 01 04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48 00 38 E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3 00 14
|
||||
bytes | CRCKey = random 16
|
||||
bytes | getCRC(CRCKey) //do it yourself
|
@ -2,14 +2,15 @@
|
||||
|
||||
## Touch
|
||||
|
||||
C -> S
|
||||
### C -> S
|
||||
|
||||
### Var
|
||||
#### Var
|
||||
type | var name | value/from
|
||||
---- | ---|---
|
||||
int |g_qq | qq number
|
||||
int| g_server| server ip
|
||||
### Packet data
|
||||
|
||||
#### Packet data
|
||||
|
||||
type | value
|
||||
---- | ---
|
||||
@ -35,4 +36,6 @@ int | g_server
|
||||
hex | 00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19
|
||||
hex | #publicKey
|
||||
|
||||
TEA加密以上, key=MD52
|
||||
### S -> C
|
||||
|
||||
[Redirection](Redirection.md)
|
@ -21,6 +21,23 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.mina</groupId>
|
||||
<artifactId>mina-core</artifactId>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-filter-ssl -->
|
||||
<dependency>
|
||||
<groupId>org.apache.mina</groupId>
|
||||
<artifactId>mina-filter-ssl</artifactId>
|
||||
<version>1.1.7</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-filter-compression -->
|
||||
<dependency>
|
||||
<groupId>org.apache.mina</groupId>
|
||||
<artifactId>mina-filter-compression</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
|
@ -5,6 +5,7 @@ import net.mamoe.mirai.event.MiraiEventManager;
|
||||
import net.mamoe.mirai.event.events.server.ServerDisableEvent;
|
||||
import net.mamoe.mirai.event.events.server.ServerEnableEvent;
|
||||
import net.mamoe.mirai.network.Robot;
|
||||
import net.mamoe.mirai.network.packet.client.touch.ClientTouchPacket;
|
||||
import net.mamoe.mirai.task.MiraiTaskManager;
|
||||
import net.mamoe.mirai.utils.LoggerTextFormat;
|
||||
import net.mamoe.mirai.utils.MiraiLogger;
|
||||
@ -16,7 +17,6 @@ import net.mamoe.mirai.utils.setting.MiraiSettingMapSection;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class MiraiServer {
|
||||
@ -98,7 +98,55 @@ public class MiraiServer {
|
||||
this.initQQConfig(qqs);
|
||||
}
|
||||
|
||||
getLogger().info("Ready to enable");
|
||||
/*
|
||||
MiraiSettingMapSection qqs = this.setting.getMapSection("qq");
|
||||
qqs.forEach((a,p) -> {
|
||||
this.getLogger().info(LoggerTextFormat.SKY_BLUE + "Finding available ports between " + "1-65536");
|
||||
try {
|
||||
int port = MiraiNetwork.getAvailablePort();
|
||||
this.getLogger().info(LoggerTextFormat.SKY_BLUE + "Listening on port " + port);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
getLogger().info("ready to connect");
|
||||
|
||||
Robot robot = new Robot(1994701021, "xiaoqqq");
|
||||
try {
|
||||
//System.out.println(Protocol.Companion.getSERVER_IP().get(3));
|
||||
//System.out.println(Protocol.Companion.getSERVER_IP().toString());
|
||||
|
||||
robot.setServerIP("14.116.136.106");
|
||||
robot.sendPacket(new ClientTouchPacket(1994701021, "14.116.136.106"));
|
||||
while (true) ;
|
||||
//robot.connect("14.116.136.106");
|
||||
//robot.connect(Protocol.Companion.getSERVER_IP().get(2));
|
||||
//robot.connect("125.39.132.242");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
/*
|
||||
System.out.println("network test");
|
||||
try {
|
||||
|
||||
|
||||
MiraiUDPServer server = new MiraiUDPServer();
|
||||
MiraiUDPClient client = new MiraiUDPClient(InetAddress.getLocalHost(),9999,MiraiNetwork.getAvailablePort());
|
||||
this.getTaskManager().repeatingTask(() -> {
|
||||
byte[] sendInfo = "test test".getBytes(StandardCharsets.UTF_8);
|
||||
try {
|
||||
client.send(new DatagramPacket(sendInfo,sendInfo.length));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
},300);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
|
||||
private void initSetting(File setting) {
|
||||
@ -134,6 +182,7 @@ public class MiraiServer {
|
||||
|
||||
MiraiConfigSection<Object> section = new MiraiConfigSection<>();
|
||||
|
||||
System.out.println("/");
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
getLogger().info(LoggerTextFormat.SKY_BLUE + "input one " + LoggerTextFormat.RED + " QQ number " + LoggerTextFormat.SKY_BLUE + "for default robot");
|
||||
getLogger().info(LoggerTextFormat.SKY_BLUE + "输入用于默认机器人的QQ号");
|
||||
@ -143,7 +192,7 @@ public class MiraiServer {
|
||||
String qqPassword = scanner.next();
|
||||
|
||||
section.put("password",qqPassword);
|
||||
section.put("owner", List.of("default"));
|
||||
section.put("owner","default");
|
||||
|
||||
this.qqs.put(String.valueOf(qqNumber),section);
|
||||
this.qqs.save();
|
||||
@ -155,34 +204,6 @@ public class MiraiServer {
|
||||
this.enabled = true;
|
||||
getLogger().info(LoggerTextFormat.GREEN + "Server enabled; Welcome to Mirai");
|
||||
getLogger().info("Mirai Version=" + MiraiServer.MIRAI_VERSION + " QQ Version=" + MiraiServer.QQ_VERSION);
|
||||
|
||||
Robot robot = new Robot(1994701021, "xiaoqqq");
|
||||
try {
|
||||
//System.out.println(Protocol.Companion.getSERVER_IP().toString());
|
||||
//robot.connect("127.0.0.1");
|
||||
robot.connect("125.39.132.242");
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
/*
|
||||
System.out.println("network test");
|
||||
try {
|
||||
|
||||
|
||||
MiraiUDPServer server = new MiraiUDPServer();
|
||||
MiraiUDPClient client = new MiraiUDPClient(InetAddress.getLocalHost(),9999,MiraiNetwork.getAvailablePort());
|
||||
this.getTaskManager().repeatingTask(() -> {
|
||||
byte[] sendInfo = "test test".getBytes(StandardCharsets.UTF_8);
|
||||
try {
|
||||
client.send(new DatagramPacket(sendInfo,sendInfo.length));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
},300);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,10 +4,8 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.mamoe.mirai.event.events.Cancellable;
|
||||
import net.mamoe.mirai.event.events.MiraiEvent;
|
||||
import net.mamoe.mirai.event.events.server.ServerDisableEvent;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@ -79,7 +77,7 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
|
||||
if(!(event instanceof Cancellable && event.isCancelled() && this.isIgnoreCancelled())){
|
||||
this.getHandler().accept((T) event);
|
||||
}
|
||||
return this.valid.test((T)event);
|
||||
return this.valid == null || this.valid.test((T) event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,150 @@
|
||||
package net.mamoe.mirai.network;
|
||||
|
||||
import org.apache.mina.core.buffer.IoBuffer;
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.apache.mina.core.session.IdleStatus;
|
||||
import org.apache.mina.core.session.IoSession;
|
||||
import org.apache.mina.filter.executor.ExecutorFilter;
|
||||
import org.apache.mina.filter.logging.LoggingFilter;
|
||||
import org.apache.mina.transport.socket.DatagramSessionConfig;
|
||||
import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class MemoryMonitorTest {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final int PORT = 8080;
|
||||
|
||||
public MemoryMonitorTest() throws IOException {
|
||||
|
||||
NioDatagramAcceptor acceptor = new NioDatagramAcceptor();//创建一个UDP的接收器
|
||||
acceptor.setHandler(new YourHandler());//设置接收器的处理程序
|
||||
|
||||
Executor threadPool = Executors.newFixedThreadPool(1500);//建立线程池
|
||||
acceptor.getFilterChain().addLast("exector", new ExecutorFilter(threadPool));
|
||||
acceptor.getFilterChain().addLast("logger", new LoggingFilter());
|
||||
|
||||
DatagramSessionConfig dcfg = acceptor.getSessionConfig();//建立连接的配置文件
|
||||
dcfg.setReadBufferSize(4096);//设置接收最大字节默认2048
|
||||
dcfg.setReceiveBufferSize(1024);//设置输入缓冲区的大小
|
||||
dcfg.setSendBufferSize(1024);//设置输出缓冲区的大小
|
||||
dcfg.setReuseAddress(true);//设置每一个非主监听连接的端口可以重用
|
||||
|
||||
acceptor.bind(new InetSocketAddress(PORT));//绑定端口
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
new MemoryMonitorTest();
|
||||
}
|
||||
|
||||
public class YourHandler extends IoHandlerAdapter {
|
||||
|
||||
//messageSent是Server响应给Clinet成功后触发的事件
|
||||
|
||||
@Override
|
||||
public void messageSent(IoSession session, Object message) throws Exception {
|
||||
if (message instanceof IoBuffer) {
|
||||
IoBuffer buffer = (IoBuffer) message;
|
||||
byte[] bb = buffer.array();
|
||||
for (int i = 0; i < bb.length; i++) {
|
||||
System.out.print((char) bb[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//抛出异常触发的事件
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(IoSession session, Throwable cause)
|
||||
throws Exception {
|
||||
cause.printStackTrace();
|
||||
session.close(true);
|
||||
}
|
||||
|
||||
//Server接收到UDP请求触发的事件
|
||||
|
||||
@Override
|
||||
public void messageReceived(IoSession session, Object message)
|
||||
throws Exception {
|
||||
System.out.println("messageReceived");
|
||||
if (message instanceof IoBuffer) {
|
||||
IoBuffer buffer = (IoBuffer) message;
|
||||
// byte[] bb = buffer.array();
|
||||
// for(int i=0;i<bb.length;i++) {
|
||||
// System.out.print((char)bb[i]);
|
||||
// }
|
||||
IoBuffer buffer1 = IoBuffer.wrap("11".getBytes());//返回信息给Clinet端
|
||||
session.write(buffer1);
|
||||
|
||||
//声明这里message必须为IoBuffer类型
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//连接关闭触发的事件
|
||||
|
||||
@Override
|
||||
public void sessionClosed(IoSession session) throws Exception {
|
||||
System.out.println("Session closed...");
|
||||
}
|
||||
|
||||
//建立连接触发的事件
|
||||
|
||||
@Override
|
||||
public void sessionCreated(IoSession session) throws Exception {
|
||||
System.out.println("Session created...");
|
||||
SocketAddress remoteAddress = session.getRemoteAddress();
|
||||
System.out.println(remoteAddress);
|
||||
|
||||
}
|
||||
|
||||
//会话空闲
|
||||
|
||||
@Override
|
||||
public void sessionIdle(IoSession session, IdleStatus status)
|
||||
throws Exception {
|
||||
System.out.println("Session idle...");
|
||||
}
|
||||
|
||||
//打开连接触发的事件,它与sessionCreated的区别在于,一个连接地址(A)第一次请求Server会建立一个Session默认超时时间为1分钟,此时若未达到超时时间这个连接地址(A)再一次向Server发送请求即是sessionOpened(连接地址(A)第一次向Server发送请求或者连接超时后向Server发送请求时会同时触发sessionCreated和sessionOpened两个事件)
|
||||
|
||||
@Override
|
||||
public void sessionOpened(IoSession session) throws Exception {
|
||||
System.out.println("Session Opened...");
|
||||
SocketAddress remoteAddress = session.getRemoteAddress();
|
||||
System.out.println(remoteAddress);
|
||||
}
|
||||
|
||||
|
||||
public void send(String host, int port) {
|
||||
|
||||
try {
|
||||
InetAddress ia = InetAddress.getByName(host);
|
||||
DatagramSocket socket = new DatagramSocket(9999);
|
||||
socket.connect(ia, port);
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
buffer = ("22")
|
||||
.getBytes();
|
||||
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
|
||||
System.out.println(dp.getLength());
|
||||
DatagramPacket dp1 = new DatagramPacket(new byte[22312], 22312);
|
||||
socket.send(dp);
|
||||
socket.receive(dp1);
|
||||
byte[] bb = dp1.getData();
|
||||
for (int i = 0; i < dp1.getLength(); i++) {
|
||||
System.out.print((char) bb[i]);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,26 +1,24 @@
|
||||
package net.mamoe.mirai.network
|
||||
|
||||
import io.netty.bootstrap.Bootstrap
|
||||
import io.netty.channel.*
|
||||
import io.netty.channel.nio.NioEventLoopGroup
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel
|
||||
import io.netty.handler.codec.bytes.ByteArrayDecoder
|
||||
import io.netty.channel.Channel
|
||||
import net.mamoe.mirai.network.packet.client.ClientPacket
|
||||
import net.mamoe.mirai.network.packet.client.login.*
|
||||
import net.mamoe.mirai.network.packet.client.touch.ClientTouchPacket
|
||||
import net.mamoe.mirai.network.packet.client.writeHex
|
||||
import net.mamoe.mirai.network.packet.server.ServerPacket
|
||||
import net.mamoe.mirai.network.packet.server.login.*
|
||||
import net.mamoe.mirai.network.packet.server.security.ServerSessionKeyResponsePacket
|
||||
import net.mamoe.mirai.network.packet.server.security.ServerSessionKeyResponsePacketEncrypted
|
||||
import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
|
||||
import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacketEncrypted
|
||||
import net.mamoe.mirai.util.getRandomKey
|
||||
import net.mamoe.mirai.util.toHexString
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import java.net.DatagramPacket
|
||||
import java.net.DatagramSocket
|
||||
import java.net.InetSocketAddress
|
||||
|
||||
/**
|
||||
* [number] is a QQ number.
|
||||
* A robot account.
|
||||
*
|
||||
* @author Him188moe
|
||||
*/
|
||||
@ -29,13 +27,13 @@ class Robot(val number: Int, private val password: String) {
|
||||
|
||||
private var channel: Channel? = null
|
||||
|
||||
private var serverIP: String = ""
|
||||
var serverIP: String = ""
|
||||
set(value) {
|
||||
serverAddress = InetSocketAddress(value, 8000)
|
||||
field = value
|
||||
}
|
||||
|
||||
private lateinit var serverAddress: InetSocketAddress;
|
||||
private lateinit var serverAddress: InetSocketAddress
|
||||
|
||||
private lateinit var token00BA: ByteArray
|
||||
private lateinit var token0825: ByteArray
|
||||
@ -64,7 +62,8 @@ class Robot(val number: Int, private val password: String) {
|
||||
when (packet) {
|
||||
is ServerTouchResponsePacket -> {
|
||||
if (packet.serverIP != null) {//redirection
|
||||
connect(packet.serverIP!!)
|
||||
serverIP = packet.serverIP!!
|
||||
//connect(packet.serverIP!!)
|
||||
sendPacket(ClientServerRedirectionPacket(packet.serverIP!!, number))
|
||||
} else {//password submission
|
||||
this.loginIP = packet.loginIP
|
||||
@ -93,7 +92,7 @@ class Robot(val number: Int, private val password: String) {
|
||||
|
||||
is ServerLoginResponseSuccessPacket -> {
|
||||
this._0828_rec_decr_key = packet._0828_rec_decr_key
|
||||
sendPacket(ClientLoginSucceedConfirmationPacket(this.number, this.serverIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105))
|
||||
sendPacket(ClientLoginSucceedConfirmationPacket(this.number, this.serverIP, this.loginIP, this.md5_32, packet.token38, packet.token88, packet.encryptionKey, this.tlv0105))
|
||||
}
|
||||
|
||||
//这个有可能是客户端发送验证码之后收到的回复验证码是否正确?
|
||||
@ -114,14 +113,15 @@ class Robot(val number: Int, private val password: String) {
|
||||
is ServerLoginResponseResendPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!))
|
||||
is ServerLoginResponseSuccessPacketEncrypted -> onPacketReceived(packet.decrypt(this.tgtgtKey!!))
|
||||
is ServerSessionKeyResponsePacketEncrypted -> onPacketReceived(packet.decrypt(this._0828_rec_decr_key))
|
||||
is ServerTouchResponsePacketEncrypted -> onPacketReceived(packet.decrypt())
|
||||
|
||||
else -> throw IllegalStateException()
|
||||
else -> throw IllegalArgumentException(packet.toString())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
private fun sendPacket(packet: ClientPacket) {
|
||||
fun sendPacket(packet: ClientPacket) {
|
||||
try {
|
||||
MiraiLogger log "Encoding"
|
||||
packet.encode()
|
||||
@ -129,19 +129,68 @@ class Robot(val number: Int, private val password: String) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
packet.writeHex(Protocol.tail)
|
||||
println(packet)
|
||||
println(packet.toByteArray().toUByteArray().toHexString())
|
||||
/*val p = DatagramPacket(packet.toByteArray());
|
||||
p.socketAddress = this.serverAddress*/
|
||||
channel!!.writeAndFlush(DatagramPacket(packet.toByteArray()))
|
||||
//ctx.writeAndFlush(packet.toByteArray()).sync()
|
||||
send(packet.toByteArray())
|
||||
//println(channel!!.writeAndFlush(packet.toByteArray()).channel().connect(serverAddress).sync().get())
|
||||
MiraiLogger info "Packet sent: $packet"
|
||||
}
|
||||
|
||||
private fun DatagramPacket(toByteArray: ByteArray): DatagramPacket = DatagramPacket(toByteArray, toByteArray.size, this.serverAddress)
|
||||
|
||||
// private val socket = DatagramSocket(15314)
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
fun send(data: ByteArray) {
|
||||
try {
|
||||
val socket = DatagramSocket((15314 + Math.random() * 5).toInt())
|
||||
socket.connect(this.serverAddress)
|
||||
|
||||
val dp1 = DatagramPacket(ByteArray(22312), 22312)
|
||||
socket.send(DatagramPacket(data, data.size))
|
||||
socket.receive(dp1)
|
||||
val zeroByte: Byte = 0
|
||||
var i = dp1.data.size - 1;
|
||||
while (dp1.data[i] == zeroByte) {
|
||||
--i
|
||||
}
|
||||
socket.close()
|
||||
onPacketReceived(ServerPacket.ofByteArray(dp1.data.copyOfRange(0, i + 1)))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
private lateinit var ctx: ChannelHandlerContext
|
||||
@ExperimentalUnsignedTypes
|
||||
@Throws(InterruptedException::class)
|
||||
fun connect(ip: String) {
|
||||
this.serverIP = ip;
|
||||
this.serverIP = ip
|
||||
|
||||
|
||||
NioDatagramConnector().let { it.handler = object : IoHandlerAdapter(), IoHandler {
|
||||
|
||||
} }
|
||||
IoConnector connector=udpClient.getConnector();
|
||||
connector.getFilterChain().addLast("codec",
|
||||
ProtocolCodecFilter(
|
||||
TextLineCodecFactory(
|
||||
Charset.forName("UTF-8"),
|
||||
LineDelimiter.WINDOWS.getValue(),
|
||||
LineDelimiter.WINDOWS.getValue())));
|
||||
|
||||
ConnectFuture connectFuture=connector.connect(udpClient.getInetSocketAddress());
|
||||
// 等待是否连接成功,相当于是转异步执行为同步执行。
|
||||
connectFuture.awaitUninterruptibly();
|
||||
//连接成功后获取会话对象。如果没有上面的等待,由于connect()方法是异步的,
|
||||
//connectFuture.getSession(),session可能会无法获取。
|
||||
udpClient.setSession(connectFuture.getSession());
|
||||
udpClient.getSession().write("Hello,UDPServer!");
|
||||
|
||||
val group = NioEventLoopGroup()
|
||||
try {
|
||||
val b = Bootstrap()
|
||||
@ -151,14 +200,17 @@ class Robot(val number: Int, private val password: String) {
|
||||
.channel(NioDatagramChannel::class.java)
|
||||
.option(ChannelOption.SO_BROADCAST, true)
|
||||
.handler(object : ChannelInitializer<NioDatagramChannel>() {
|
||||
|
||||
override fun channelActive(ctx: ChannelHandlerContext?) {
|
||||
this@Robot.ctx = ctx!!
|
||||
super.channelActive(ctx)
|
||||
}
|
||||
|
||||
@Throws(Exception::class)
|
||||
override fun initChannel(ch: NioDatagramChannel) {
|
||||
/*ch.pipeline().addLast(object : MessageToMessageEncoder<ByteArray>() {
|
||||
override fun encode(ctx: ChannelHandlerContext?, msg: ByteArray?, out: MutableList<Any>?) {
|
||||
out!!.add(DatagramPacket(msg!!))
|
||||
}
|
||||
})*/
|
||||
ch.pipeline().addLast(ByteArrayDecoder())
|
||||
ch.pipeline().addLast(ByteArrayEncoder())
|
||||
|
||||
ch.pipeline().addLast(object : SimpleChannelInboundHandler<ByteArray>() {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, bytes: ByteArray) {
|
||||
try {
|
||||
@ -172,6 +224,20 @@ class Robot(val number: Int, private val password: String) {
|
||||
MiraiLogger.catching(cause)
|
||||
}
|
||||
})
|
||||
|
||||
ch.pipeline().addLast(object : SimpleChannelInboundHandler<DatagramPacket>() {
|
||||
override fun channelRead0(ctx: ChannelHandlerContext, bytes: DatagramPacket) {
|
||||
try {
|
||||
this@Robot.onPacketReceived(ServerPacket.ofByteArray(bytes.data))
|
||||
} catch (e: Exception) {
|
||||
MiraiLogger.catching(e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
|
||||
MiraiLogger.catching(cause)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@ -183,5 +249,5 @@ class Robot(val number: Int, private val password: String) {
|
||||
} finally {
|
||||
group.shutdownGracefully().sync()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor
|
||||
class ClientLoginSucceedConfirmationPacket(
|
||||
private val qq: Int,
|
||||
private val serverIp: String,
|
||||
private val loginIP: String,
|
||||
private val md5_32: ByteArray,
|
||||
private val token38: ByteArray,
|
||||
private val token88: ByteArray,
|
||||
@ -111,7 +112,7 @@ class ClientLoginSucceedConfirmationPacket(
|
||||
this.writeHex("68")
|
||||
|
||||
this.writeHex("00 00 00 00 00 2D 00 06 00 01")
|
||||
this.writeIP("127.0.0.1")//本地IP地址? todo test that
|
||||
this.writeIP(loginIP)//本地IP地址? todo test that
|
||||
|
||||
return super.toByteArray()
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import net.mamoe.mirai.network.packet.client.ClientPacket
|
||||
import net.mamoe.mirai.network.packet.client.writeHex
|
||||
import net.mamoe.mirai.network.packet.client.writeIP
|
||||
import net.mamoe.mirai.network.packet.client.writeQQ
|
||||
import net.mamoe.mirai.util.ByteArrayDataOutputStream
|
||||
import net.mamoe.mirai.util.TEACryptor
|
||||
import net.mamoe.mirai.util.hexToBytes
|
||||
import java.io.IOException
|
||||
@ -25,9 +26,9 @@ class ClientServerRedirectionPacket(private val serverIP: String, private val qq
|
||||
this.writeHex(Protocol.redirectionKey)
|
||||
|
||||
|
||||
this.write(TEACryptor.encrypt(object : ClientPacket() {
|
||||
this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
|
||||
@Throws(IOException::class)
|
||||
override fun encode() {
|
||||
override fun toByteArray(): ByteArray {
|
||||
this.writeHex(Protocol._0825data0)
|
||||
this.writeHex(Protocol._0825data2)
|
||||
this.writeQQ(qq)
|
||||
@ -35,7 +36,8 @@ class ClientServerRedirectionPacket(private val serverIP: String, private val qq
|
||||
this.writeIP(serverIP)
|
||||
this.writeHex("01 6F A1 58 22 01 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 03 00 19")
|
||||
this.writeHex(Protocol.publicKey)
|
||||
return super.toByteArray()
|
||||
}
|
||||
}.encodeToByteArray(), Protocol.redirectionKey.hexToBytes()))
|
||||
}.toByteArray(), Protocol.redirectionKey.hexToBytes()))
|
||||
}
|
||||
}
|
@ -38,10 +38,12 @@ class ClientTouchPacket(val qq: Int, val serverIp: String) : ClientPacket() {
|
||||
this.writeQQ(qq)
|
||||
this.writeHex("00 00 00 00 03 09 00 08 00 01")
|
||||
//this.writeIP("192.168.1.1");
|
||||
println("serverIp=$serverIp")
|
||||
this.writeIP(serverIp);
|
||||
//this.writeIP("123456789")
|
||||
this.writeHex("00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19")
|
||||
this.writeHex(Protocol.publicKey)
|
||||
println(super.toUByteArray().toHexString())
|
||||
return super.toByteArray()
|
||||
}
|
||||
}.toByteArray()))
|
||||
|
@ -19,7 +19,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
fun ofByteArray(bytes: ByteArray): ServerPacket {
|
||||
println("Raw received: $bytes")
|
||||
println("Raw received: ${bytes.toUByteArray().toHexString()}")
|
||||
|
||||
val stream = bytes.dataInputStream()
|
||||
|
||||
@ -78,10 +78,9 @@ fun DataInputStream.readUntil(byte: Byte): ByteArray {
|
||||
fun DataInputStream.readIP(): String {
|
||||
var buff = ""
|
||||
for (i in 0..3) {
|
||||
val byte = readByte()
|
||||
buff += (byte.toUByte().toString())
|
||||
val byte = readUnsignedByte()
|
||||
buff += byte.toString()
|
||||
if (i != 3) buff += "."
|
||||
println(byte.toHexString())
|
||||
}
|
||||
return buff
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ class ServerLoginResponseSuccessPacketEncrypted(input: DataInputStream, val leng
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
fun decrypt(tgtgtKey: ByteArray): ServerLoginResponseSuccessPacket {//todo test
|
||||
this.input.skip(14)
|
||||
this.input.skip(7)
|
||||
return ServerLoginResponseSuccessPacket(TEACryptor.decrypt(TEACryptor.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, Protocol.shareKey.hexToBytes()), tgtgtKey).dataInputStream(), length);
|
||||
//TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key)
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ class ServerSessionKeyResponsePacketEncrypted(inputStream: DataInputStream) : Se
|
||||
}
|
||||
|
||||
fun decrypt(_0828_rec_decr_key: ByteArray): ServerSessionKeyResponsePacket {//todo test
|
||||
this.input.skip(14)
|
||||
this.input.skip(7)
|
||||
return ServerSessionKeyResponsePacket(TEACryptor.decrypt(this.input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, _0828_rec_decr_key).dataInputStream());
|
||||
//TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key)
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import net.mamoe.mirai.network.packet.server.ServerPacket
|
||||
import net.mamoe.mirai.network.packet.server.readIP
|
||||
import net.mamoe.mirai.util.TEACryptor
|
||||
import net.mamoe.mirai.util.getRandomKey
|
||||
import net.mamoe.mirai.util.hexToBytes
|
||||
import net.mamoe.mirai.util.toHexString
|
||||
import java.io.DataInputStream
|
||||
|
||||
/**
|
||||
@ -17,7 +19,7 @@ import java.io.DataInputStream
|
||||
* @author Him188moe
|
||||
*/
|
||||
@ToString
|
||||
class ServerTouchResponsePacket(private val type: Type, inputStream: DataInputStream) : ServerPacket(inputStream) {
|
||||
class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
|
||||
var serverIP: String? = null;
|
||||
|
||||
var loginTime: Int = 0
|
||||
@ -32,12 +34,12 @@ class ServerTouchResponsePacket(private val type: Type, inputStream: DataInputSt
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
override fun decode() {
|
||||
when (input.readByte().toInt()) {
|
||||
when (val id = input.readByte().toUByte().toInt()) {
|
||||
0xFE -> {
|
||||
input.skip(94)
|
||||
serverIP = input.readIP()
|
||||
}
|
||||
0X00 -> {
|
||||
0x00 -> {
|
||||
input.skip(4)
|
||||
token = input.readNBytes(56)
|
||||
input.skip(6)
|
||||
@ -48,7 +50,7 @@ class ServerTouchResponsePacket(private val type: Type, inputStream: DataInputSt
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalStateException()
|
||||
throw IllegalStateException(arrayOf(id.toUByte()).toUByteArray().toHexString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,11 +61,16 @@ class ServerTouchResponsePacketEncrypted(private val type: ServerTouchResponsePa
|
||||
|
||||
}
|
||||
|
||||
@ExperimentalUnsignedTypes
|
||||
fun decrypt(): ServerTouchResponsePacket {
|
||||
input.skip(14)
|
||||
return ServerTouchResponsePacket(type, DataInputStream(TEACryptor.decrypt(input.readAllBytes().let { it.copyOfRange(0, it.size - 1) }, when (type) {
|
||||
ServerTouchResponsePacket.Type.TYPE_08_25_31_01 -> Protocol.redirectionKey.toByteArray()
|
||||
ServerTouchResponsePacket.Type.TYPE_08_25_31_02 -> Protocol._0825key.toByteArray()
|
||||
input.skip(7)
|
||||
var bytes = input.readAllBytes();
|
||||
bytes = bytes.copyOfRange(0, bytes.size - 1);
|
||||
println(bytes.toUByteArray().toHexString())
|
||||
|
||||
return ServerTouchResponsePacket(DataInputStream(TEACryptor.decrypt(bytes, when (type) {
|
||||
ServerTouchResponsePacket.Type.TYPE_08_25_31_02 -> Protocol.redirectionKey.hexToBytes()
|
||||
ServerTouchResponsePacket.Type.TYPE_08_25_31_01 -> Protocol._0825key.hexToBytes()
|
||||
}).inputStream()));
|
||||
}
|
||||
}
|
@ -177,7 +177,7 @@ public class TEACryptor {
|
||||
|
||||
private byte[] decrypt(byte[] ciphertext, int offset, int len) {
|
||||
if (len % 8 != 0 || len < 16) {
|
||||
return null;
|
||||
throw new IllegalArgumentException("must len % 8 == 0 && len >= 16");
|
||||
}
|
||||
mIV = decode(ciphertext, offset);
|
||||
mIndexPos = mIV[0] & 7;
|
||||
@ -199,7 +199,7 @@ public class TEACryptor {
|
||||
if (mIndexPos == 8) {
|
||||
isFirstBlock = false;
|
||||
if (!decodeOneBlock(ciphertext, offset, len)) {
|
||||
return null;
|
||||
throw new RuntimeException("Unable to decode");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,14 +215,14 @@ public class TEACryptor {
|
||||
mPreOutPos = mOutPos - 8;
|
||||
isFirstBlock = false;
|
||||
if (!decodeOneBlock(ciphertext, offset, len)) {
|
||||
return null;
|
||||
throw new RuntimeException("Unable to decode");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (g = 0; g < 7; g++) {
|
||||
if (mIndexPos < 8) {
|
||||
if ((ciphertext[mPreOutPos + offset + mIndexPos] ^ mIV[mIndexPos]) != 0) {
|
||||
return null;
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
++mIndexPos;
|
||||
}
|
||||
@ -231,7 +231,7 @@ public class TEACryptor {
|
||||
if (mIndexPos == 8) {
|
||||
mPreOutPos = mOutPos;
|
||||
if (!decodeOneBlock(ciphertext, offset, len)) {
|
||||
return null;
|
||||
throw new RuntimeException("Unable to decode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ object MiraiLogger {
|
||||
this.print(o.toString())
|
||||
}
|
||||
|
||||
infix fun log(o: Any?) = MiraiLogger.info(o)
|
||||
infix fun log(o: Any?) = info(o)
|
||||
|
||||
infix fun println(o: Any?) = MiraiLogger.info(o)
|
||||
infix fun println(o: Any?) = info(o)
|
||||
|
||||
infix fun debug(o: Any?) {
|
||||
this.print(o.toString())
|
||||
|
@ -2,6 +2,7 @@ package net.mamoe.mirai.utils.config;
|
||||
|
||||
import net.mamoe.mirai.MiraiServer;
|
||||
import net.mamoe.mirai.utils.Utils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
@ -9,27 +10,34 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* YAML-TYPE CONFIG
|
||||
* Thread SAFE
|
||||
*
|
||||
* @author NaturalHG
|
||||
*/
|
||||
public class MiraiConfig extends MiraiConfigSection<Object>{
|
||||
public class MiraiConfig extends MiraiConfigSection<Object> {
|
||||
|
||||
private volatile File root;
|
||||
private final File root;
|
||||
|
||||
public MiraiConfig(File file){
|
||||
public MiraiConfig(@NotNull String configName) {
|
||||
this(new File(MiraiServer.getInstance().getParentFolder(), Objects.requireNonNull(configName)));
|
||||
}
|
||||
|
||||
public MiraiConfig(@NotNull File file) {
|
||||
super();
|
||||
if(!file.toURI().getPath().contains(MiraiServer.getInstance().getParentFolder().getPath())){
|
||||
file = new File((MiraiServer.getInstance().getParentFolder().getPath() + "/" + file).replace("//","/"));
|
||||
}
|
||||
Objects.requireNonNull(file);
|
||||
/*if (!file.toURI().getPath().contains(MiraiServer.getInstance().getParentFolder().getPath())) {
|
||||
file = new File(MiraiServer.getInstance().getParentFolder().getPath(), file.getName());
|
||||
}*/
|
||||
|
||||
this.root = file;
|
||||
|
||||
if(!file.exists()){
|
||||
if (!file.exists()) {
|
||||
try {
|
||||
if(!file.createNewFile()){
|
||||
if (!file.createNewFile()) {
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@ -39,31 +47,27 @@ public class MiraiConfig extends MiraiConfigSection<Object>{
|
||||
this.parse();
|
||||
}
|
||||
|
||||
private MiraiConfig(){
|
||||
|
||||
}
|
||||
|
||||
public synchronized void save(){
|
||||
public synchronized void save() {
|
||||
DumperOptions dumperOptions = new DumperOptions();
|
||||
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
Yaml yaml = new Yaml(dumperOptions);
|
||||
String content = yaml.dump(this);
|
||||
try {
|
||||
Utils.writeFile(this.root,content);
|
||||
Utils.writeFile(this.root, content);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void parse(){
|
||||
private void parse() {
|
||||
DumperOptions dumperOptions = new DumperOptions();
|
||||
dumperOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
Yaml yaml = new Yaml(dumperOptions);
|
||||
this.clear();
|
||||
try {
|
||||
Map<String,Object> content = yaml.loadAs(Utils.readFile(this.root), LinkedHashMap.class);
|
||||
if(content != null) {
|
||||
Map<String, Object> content = yaml.loadAs(Utils.readFile(this.root), LinkedHashMap.class);
|
||||
if (content != null) {
|
||||
this.putAll(content);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@ -72,5 +76,4 @@ public class MiraiConfig extends MiraiConfigSection<Object>{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
7
pom.xml
7
pom.xml
@ -94,6 +94,13 @@
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
|
||||
<dependency>
|
||||
<groupId>org.apache.mina</groupId>
|
||||
<artifactId>mina-core</artifactId>
|
||||
<version>2.1.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
|
||||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
|
Loading…
Reference in New Issue
Block a user