mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-30 02:30:12 +08:00
update
This commit is contained in:
parent
e1f706f76d
commit
9be18408f8
5
.gitignore
vendored
5
.gitignore
vendored
@ -28,4 +28,7 @@ hs_err_pid*
|
||||
mirai.iml
|
||||
/.idea/
|
||||
.idea/*
|
||||
/.idea/*
|
||||
/.idea/*
|
||||
|
||||
test/
|
||||
/test
|
@ -35,7 +35,6 @@ hex | 00 00 00 00 03 09 00 08 00 01
|
||||
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
|
||||
|
||||
|
@ -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>
|
||||
|
@ -4,8 +4,8 @@ import lombok.Getter;
|
||||
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.Protocol;
|
||||
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;
|
||||
@ -116,11 +116,16 @@ public class MiraiServer {
|
||||
|
||||
Robot robot = new Robot(1994701021, "xiaoqqq");
|
||||
try {
|
||||
System.out.println(Protocol.Companion.getSERVER_IP().get(3));
|
||||
//System.out.println(Protocol.Companion.getSERVER_IP().get(3));
|
||||
//System.out.println(Protocol.Companion.getSERVER_IP().toString());
|
||||
robot.connect(Protocol.Companion.getSERVER_IP().get(3));
|
||||
|
||||
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 (InterruptedException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
@ -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,22 +1,20 @@
|
||||
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
|
||||
|
||||
/**
|
||||
@ -29,7 +27,7 @@ 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
|
||||
@ -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
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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