This commit is contained in:
Him188moe 2019-08-21 21:25:27 +08:00
parent d02704bebb
commit cd5da2ddc7
11 changed files with 136 additions and 218 deletions

View File

@ -21,21 +21,10 @@
</parent>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
<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>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
</dependency>
<dependency>

View File

@ -22,4 +22,12 @@ class QQ(number: Int) : Contact(number) {
fun at(): String {
return "[@$number]"
}
/*
Make that we can use (QQ + QQ2 + QQ3).sendMessage( )
operator fun plus(qq: QQ): QQCombination {
}*/
}

View File

@ -1,150 +0,0 @@
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();
}
}
}
}

View File

@ -1,6 +1,8 @@
package net.mamoe.mirai.network
import io.netty.channel.Channel
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import net.mamoe.mirai.network.packet.client.ClientPacket
import net.mamoe.mirai.network.packet.client.login.*
import net.mamoe.mirai.network.packet.client.writeHex
@ -129,18 +131,16 @@ 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*/
//ctx.writeAndFlush(packet.toByteArray()).sync()
send(packet.toByteArray())
MiraiLogger info "Sending: $packet"
GlobalScope.launch {
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
@ -151,6 +151,7 @@ class Robot(val number: Int, private val password: String) {
val dp1 = DatagramPacket(ByteArray(22312), 22312)
socket.send(DatagramPacket(data, data.size))
MiraiLogger info "Packet sent: ${data.toUByteArray().toHexString()}"
socket.receive(dp1)
val zeroByte: Byte = 0
var i = dp1.data.size - 1;

View File

@ -41,7 +41,7 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
* Encode this packet.
*
*
* Before sending the packet, an [tail][Protocol.tail] will be added.
* Before sending the packet, a [tail][Protocol.tail] will be added.
*/
@Throws(IOException::class)
abstract fun encode()
@ -99,6 +99,22 @@ fun DataOutputStream.writeVarInt(dec: UInt) {
throw UnsupportedOperationException()
}
fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) {
this.write(TEACryptor.encrypt(byteArray, key))
}
fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, cryptor: TEACryptor) {
this.write(cryptor.encrypt(byteArray))
}
fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: DataOutputStream.() -> Unit) {
this.write(TEACryptor.encrypt(ByteArrayDataOutputStream().let { it.encoder(); it.toByteArray() }, key))
}
fun DataOutputStream.encryptAndWrite(cryptor: TEACryptor, encoder: DataOutputStream.() -> Unit) {
this.write(cryptor.encrypt(ByteArrayDataOutputStream().let { it.encoder(); it.toByteArray() }))
}
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) {
@ -112,7 +128,7 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log
val md5_1 = md5(password);
val md5_2 = md5(md5_1 + "00 00 00 00".hexToBytes() + qq.toByteArray())
it.write(md5_1)
it.writeInt(loginTime)//todo FIXED 12(maybe 11???) bytes??? check that
it.writeInt(loginTime)
it.writeByte(0);
it.writeZero(4 * 3)
it.writeIP(loginIP)
@ -124,27 +140,44 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log
}
@ExperimentalUnsignedTypes
fun DataOutputStream.writeCRC32() {
getRandomKey(16).let {
fun DataOutputStream.writeCRC32() = writeCRC32(getRandomKey(16))
@ExperimentalUnsignedTypes
fun DataOutputStream.writeCRC32(key: ByteArray) {
key.let {
write(it)//key
writeLong(getCrc32(it))//todo may be int? check that.
writeInt(getCrc32(it))
}
}
fun DataOutputStream.writeHostname() {
val hostName: String = InetAddress.getLocalHost().hostName.let { it.substring(0, it.length - 3) };
this.writeShort(hostName.length / 2);//todo check that
this.writeShort(hostName.length);
this.writeBytes(hostName)//todo 这个对吗?
fun DataOutputStream.writeDeviceName() {
val deviceName = InetAddress.getLocalHost().hostName
this.writeShort(deviceName.length + 2)
this.writeShort(deviceName.length)
this.writeBytes(deviceName)
}
fun Int.toByteArray(): ByteArray = byteArrayOf(//todo 检查这方法对不对, 这其实就是从 DataInputStream copy来的
/**
* 255 -> 00 00 00 FF
*/
fun Int.toByteArray(): ByteArray = byteArrayOf(
(this.ushr(24) and 0xFF).toByte(),
(this.ushr(16) and 0xFF).toByte(),
(this.ushr(8) and 0xFF).toByte(),
(this.ushr(0) and 0xFF).toByte()
)
/**
* 255 -> FF 00 00 00
*/
fun Int.toLByteArray(): ByteArray = byteArrayOf(
(this.ushr(0) and 0xFF).toByte(),
(this.ushr(8) and 0xFF).toByte(),
(this.ushr(16) and 0xFF).toByte(),
(this.ushr(24) and 0xFF).toByte()
)
@ExperimentalUnsignedTypes
fun Int.toHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toHexString(separator);
@ -155,14 +188,14 @@ private fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD
@ExperimentalUnsignedTypes
@Throws(IOException::class)
fun DataOutputStream.writeZero(count: Int) {
for (x in 0..count) {
repeat(count) {
this.writeByte(0)
}
}
@Throws(IOException::class)
fun DataOutputStream.writeRandom(length: Int) {
for (i in 0 until length) {
repeat(length) {
this.writeByte((Math.random() * 255).toInt().toByte().toInt())
}
}

View File

@ -7,6 +7,7 @@ import net.mamoe.mirai.util.ByteArrayDataOutputStream
import net.mamoe.mirai.util.TEACryptor
import net.mamoe.mirai.util.getRandomKey
import net.mamoe.mirai.util.hexToBytes
import java.net.InetAddress
/**
* Password submission (0836_622)
@ -15,7 +16,14 @@ import net.mamoe.mirai.util.hexToBytes
*/
@PacketId("08 36 31 03")
@ExperimentalUnsignedTypes
class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: Int, private val loginIP: String, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() {
class ClientPasswordSubmissionPacket(
private val qq: Int,
private val password: String,
private val loginTime: Int,
private val loginIP: String,
private val tgtgtKey: ByteArray,
private val token0825: ByteArray
) : ClientPacket() {
@ExperimentalUnsignedTypes
override fun encode() {
this.writeQQ(qq)
@ -24,13 +32,10 @@ class ClientPasswordSubmissionPacket(private val qq: Int, private val password:
this.writeHex("00 00 00 10")
this.writeHex(Protocol._0836key1)
this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
override fun toByteArray(): ByteArray {
writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
writePart2()
return super.toByteArray()
}
}.toByteArray(), Protocol.shareKey.hexToBytes()))
this.encryptAndWrite(Protocol.shareKey.hexToBytes()) {
writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
writePart2()
}
}
}
@ -68,6 +73,10 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor
}
}
fun main() {
println(InetAddress.getLocalHost().hostAddress)
}
@ExperimentalUnsignedTypes
@PacketId("08 28 04 34")
class ClientLoginSucceedConfirmationPacket(
@ -112,7 +121,7 @@ class ClientLoginSucceedConfirmationPacket(
this.writeHex("68")
this.writeHex("00 00 00 00 00 2D 00 06 00 01")
this.writeIP(loginIP)//本地IP地址? todo test that
this.writeIP(InetAddress.getLocalHost().hostName)//? todo 这随便扔的
return super.toByteArray()
}
@ -126,12 +135,12 @@ class ClientLoginSucceedConfirmationPacket(
@ExperimentalUnsignedTypes
private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray) {
this.writeQQ(System.currentTimeMillis().toInt())//that's correct
this.writeInt(System.currentTimeMillis().toInt())
this.writeHex("01 12")//tag
this.writeHex("00 38")//length
this.write(token0825)//length
this.writeHex("03 0F")//tag
this.writeHostname()//todo 务必检查这个
this.writeDeviceName()
/*易语言源码: PCName就是HostName
PCName BytesToStr (Ansi转Utf8 (取主机名 ()))
PCName 取文本左边 (PCName, 取文本长度 (PCName) 3)*/

View File

@ -56,6 +56,10 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
}
}
override fun toString(): String {
return this.javaClass.simpleName + this.javaClass.declaredFields.joinToString(", ", "{", "}") { it.trySetAccessible(); it.name + "=" + it.get(this) }
}
}

View File

@ -1,6 +1,5 @@
package net.mamoe.mirai.network.packet.server.touch
import lombok.ToString
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.server.ServerPacket
import net.mamoe.mirai.network.packet.server.readIP
@ -18,7 +17,6 @@ import java.io.DataInputStream
*
* @author Him188moe
*/
@ToString
class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
var serverIP: String? = null;

View File

@ -28,28 +28,37 @@ object Utils {
}
}
fun ByteArray.toHexString(): String = toHexString(" ")
fun ByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator)
@ExperimentalUnsignedTypes
fun UByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator)
@ExperimentalUnsignedTypes
fun Byte.toHexString(): String = this.toUByte().toString(16)
fun UByteArray.toHexString(): String = toHexString(" ")
@ExperimentalUnsignedTypes
fun Byte.toHexString(): String = this.toUByte().toString(16)
@ExperimentalUnsignedTypes
fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
@ExperimentalUnsignedTypes
fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
@ExperimentalUnsignedTypes//todo test that
@ExperimentalUnsignedTypes
fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() }
@ExperimentalUnsignedTypes
fun String.hexToByte(): Byte = hexToBytes()[0]
open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) {
open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
@ExperimentalUnsignedTypes
open fun toUByteArray(): UByteArray = (out as ByteArrayOutputStream).toByteArray().toUByteArray();
}
fun lazyEncode(t: ByteArrayDataOutputStream.() -> Unit): ByteArray = ByteArrayDataOutputStream().let { it.t(); return it.toByteArray() }
@ExperimentalUnsignedTypes
fun getRandomKey(length: Int): ByteArray {
val bytes = LinkedList<Byte>();
@ -57,4 +66,4 @@ fun getRandomKey(length: Int): ByteArray {
return bytes.toByteArray();
}
fun getCrc32(key: ByteArray): Long = with(CRC32()) { update(key); return@with this.value };
fun getCrc32(key: ByteArray): Int = CRC32().let { it.update(key); it.value.toInt() }

View File

@ -13,11 +13,13 @@ public class HaxComparator {
private static String GREEN = "\033[33m";
private static String UNKNOWN = "\033[30m";
public static String compare(String hax1s, String hax2s){
StringBuilder builder = new StringBuilder();
String[] hax1 = hax1s.trim().split(" ");
String[] hax2 = hax2s.trim().split(" ");
String[] hax1 = hax1s.trim().replace("\n", "").split(" ");
String[] hax2 = hax2s.trim().replace("\n", "").split(" ");
if(hax1.length == hax2.length){
builder.append(GREEN).append("长度一致:").append(hax1.length);
@ -25,6 +27,8 @@ public class HaxComparator {
builder.append(RED).append("长度不一致").append(hax1.length).append("/").append(hax2.length);
}
StringBuilder numberLine = new StringBuilder();
StringBuilder hax1b = new StringBuilder();
StringBuilder hax2b = new StringBuilder();
int dif = 0;
@ -61,18 +65,37 @@ public class HaxComparator {
}
}
hax1b.append(h1).append(" ");
hax2b.append(h2).append(" ");
numberLine.append(UNKNOWN).append(getNumber(i)).append(" ");
hax1b.append(h1).append(" ");
hax2b.append(h2).append(" ");
if(isDif){
++dif;
}
}
return (builder.append(" ").append(dif).append(" 个不同").append("\n").append(hax1b).append("\n").append(hax2b)).toString();
return (builder.append(" ").append(dif).append(" 个不同").append("\n")
.append(numberLine).append("\n")
.append(hax1b).append("\n")
.append(hax2b))
.toString();
}
private static String getNumber(int number) {
if (number < 10) {
return "00" + number;
}
if (number < 100) {
return "0" + number;
}
return String.valueOf(number);
}
public static void main(String[] args){
System.out.println(HaxComparator.compare("00 01 09 00 70 00 01 23 7B FE 83 D1 37 64 46 84 9D E9 9C E7 BB 8E 44 00 38 9B A4 3B C2 BB 49 4C DA B0 A5 5C C8 27 29 74 EF CB 38 59 4E 03 C8 15 C6 F9 BF 3F 88 22 7E 22 5B 48 02 71 59 1A 2C C8 42 BA 81 76 66 0C 46 91 89 6C B2 17 BF 2A 00 F8 8B 00 20 7C 28 07 3D AA 24 EF B4 49 9D 85 7F 4C F5 41 56 F4 1F AD 53 81 9F C1 03 F3 03 65 DD 0C 04 CC 68 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6","AA CC AA DD EE GG HH"));
System.out.println(HaxComparator.compare(
"02 37 13 08 28 31 03 76 E4 B8 DD 03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19 02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3 00 00 00 10 EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA B4 4E C2 36 01 12 00 38 A9 76 88 3D C3 26 28 32 77 D1 EA 55 23 52 12 A5 75 1F EB F9 3B 6D 36 50 5E CF 8E 16 16 19 10 6B 83 FA 6F 0E D6 8E ED A4 BF BC 6C DE 34 61 D9 BB 96 16 C5 CE FE 76 27 22 03 0F 00 11 00 0F 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55 00 05 00 06 00 02 76 E4 B8 DD 00 06 00 78 9F DE A7 F7 6D 6C B3 D6 91 47 B8 3D 97 EB 79 ED 82 A6 9C 77 1E FC 74 C6 0C 31 99 DA 97 21 CD 90 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 00 1A 00 40 2D FB 2B 26 88 BE 00 43 A9 25 00 06 5A DD D3 1F 7D 95 9C A3 50 25 C4 65 F8 C6 0E 09 A0 00 30 57 26 13 7F 5A C6 01 F8 F6 63 4C 67 13 B3 B1 0F 30 89 60 81 B8 1A CD D5 02 FB 26 45 A5 27 79 34 D0 00 18 00 16 00 01 00 00 04 53 00 00 00 01 00 00 15 85 76 E4 B8 DD 00 00 00 00 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 10 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 00 00 00 00 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 54 30 26 84 06 E4 97 E3 63 37 C5 8C 34 72 2D C3 6B 74 83 4C 57 17 EF 65 F7 66 94 6B 2A A4 7F E9 72 11 3B 33 0A 03\n"
,
"02 37 13 08 36 31 03 76 E4 B8 DD 03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19 02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3 00 00 00 10 EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA B4 15 18 27 01 12 00 38 C3 D9 67 C5 43 ED E4 FF 64 B7 68 80 19 4E AA 17 C2 77 C0 51 82 E0 E1 35 1C E5 B6 50 49 AE 16 51 F3 59 B4 B2 00 E8 ED AD 99 6D 09 2C D6 0F 73 09 D6 44 DE 74 58 C5 24 B2 03 0F 00 11 00 0F 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55 00 05 00 06 00 02 76 E4 B8 DD 00 06 00 78 D8 20 30 26 EB 91 D2 66 ED A2 73 A1 1F BA C0 BD C6 5C F0 35 83 CB 24 0B FE 62 5F C0 1F 74 6D F0 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 00 1A 00 40 B1 AC 22 BA AE F3 4F 8F A9 16 BB 14 BA 10 00 BA 47 87 E3 5F A0 C6 1F 14 F5 34 AC E2 5C 9E 2F C6 F7 04 52 E1 9D FC 5C BE A4 7F 38 D8 D8 C4 08 51 D6 9E 37 16 8E 24 DF A2 5B 5D DB AB 2E 00 76 EE 00 18 00 16 00 01 00 00 04 53 00 00 00 01 00 00 15 85 76 E4 B8 DD 00 00 00 00 00 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 10 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 00 00 00 00 00 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 5F C9 F5 37 A0 11 D7 E6 26 37 A3 2B E3 21 11 83 F0 65 32 06 6A BC 59 C4 20 9F 84 E8 C9 FE 8F 3B 6D 96 12 F2 A4 03\n"
));
}
}

20
pom.xml
View File

@ -63,12 +63,6 @@
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.intellij</groupId>
@ -94,13 +88,6 @@
<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>
@ -114,6 +101,13 @@
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.3.0-M2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<dependency>
<groupId>io.netty</groupId>