From a2fae796fa42ee92758cd32c16c56002400ac86c Mon Sep 17 00:00:00 2001 From: Him188moe Date: Thu, 8 Aug 2019 21:16:26 +0800 Subject: [PATCH 1/3] update project structure --- mirai-core/pom.xml | 7 + .../java/net/mamoe/mirai/network/Network.java | 58 +++++++++ .../mirai/network/NetworkPacketHandler.java | 123 ++++++++++++++++++ pom.xml | 7 + 4 files changed, 195 insertions(+) create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/Network.java create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/NetworkPacketHandler.java diff --git a/mirai-core/pom.xml b/mirai-core/pom.xml index 8b364e28b..4e198fc6b 100644 --- a/mirai-core/pom.xml +++ b/mirai-core/pom.xml @@ -38,6 +38,13 @@ ../pom.xml + + + io.netty + netty-all + + + diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/Network.java b/mirai-core/src/main/java/net/mamoe/mirai/network/Network.java new file mode 100644 index 000000000..4765e53b5 --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/Network.java @@ -0,0 +1,58 @@ +package net.mamoe.mirai.network; + +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.bytes.ByteArrayDecoder; +import io.netty.handler.codec.bytes.ByteArrayEncoder; + +/** + * JPRE 网络层启动器. + * 本类用于启动网络服务器. 包接受器请参考 {@link NetworkPacketHandler} + * (插件请不要使用本类, 用了也会因端口占用而抛出异常) + * + * @author Him188 @ JPRE Project + */ +public final class Network { + private static ServerBootstrap server; + + /** + * 启动网络服务器. 会阻塞线程直到关闭网络服务器. + * + * @param port 端口号 + * @throws RuntimeException 服务器已经启动时抛出 + */ + public static void start(int port) throws InterruptedException { + if (server != null) { + throw new RuntimeException("there is already a ServerBootstrap instance"); + } + + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + try { + server = new ServerBootstrap(); + server.group(bossGroup, workerGroup); + server.channel(NioServerSocketChannel.class); + //b.option(ChannelOption.SO_BACKLOG, 100); + //b.handler(new LoggingHandler(LogLevel.INFO)); + server.childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast("bytesDecoder", new ByteArrayDecoder()); + pipeline.addLast("bytesEncoder", new ByteArrayEncoder()); + pipeline.addLast("handler", new NetworkPacketHandler()); + } + }); + + server.bind(port).sync().channel().closeFuture().sync(); + } finally { + bossGroup.shutdownGracefully(); + workerGroup.shutdownGracefully(); + } + } +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/NetworkPacketHandler.java b/mirai-core/src/main/java/net/mamoe/mirai/network/NetworkPacketHandler.java new file mode 100644 index 000000000..9cd0e6caa --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/NetworkPacketHandler.java @@ -0,0 +1,123 @@ +package net.mamoe.mirai.network; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +import java.io.IOException; +import java.net.InetSocketAddress; + +/** + * 网络数据包接收器. 该类属于网络层, 插件一般不需要使用 + * + * @author Him188 @ JPRE Project + */ +public class NetworkPacketHandler extends SimpleChannelInboundHandler { + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + super.channelRead(ctx, msg); + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, byte[] data) throws Exception { + synchronized (this) { + handlePacket(ctx, data); + } + } + + private byte[] temp = new byte[0]; + + + /** + * Synchronized by {@code synchronized (this)} in {@link #channelRead0} + */ + private void handlePacket(ChannelHandlerContext ctx, byte[] data) { + try { + temp = Utils.arrayAppend(temp, data); + while (temp.length != 0) { + int position = Utils.arraySearch(temp, Protocol.SIGNATURE); + if (position < 0) { + return;//收到的是子包, 数据未结尾 + } + + byte[] d = Utils.arrayGetCenter(temp, 0, position); + temp = Utils.arrayDelete(temp, position + Protocol.SIGNATURE.length); + + JPREMain.getInstance().getScheduler().addTask(() -> processPacket(ctx, d)); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + //TODO 改为 public, 并将 ctx 改为插件可扩展的消息源以实现多源化 + private void processPacket(ChannelHandlerContext ctx, byte[] data) { + if (data.length == 0) { + return; + } + processPacket(ctx, new BinaryStream(data)); + } + + private void processPacket(ChannelHandlerContext ctx, BinaryStream stream) { + //System.out.println(stream); + for (MPQClient client : clients) { + if (client.is((InetSocketAddress) ctx.channel().remoteAddress())) { + client.getFrame().getScheduler().addTask(() -> { + try { + client.dataReceive(stream); + } catch (Exception e) { + e.printStackTrace(); + } + }); + return; + } + } + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + if (cause instanceof IOException) { //远程主机强迫关闭了一个现有的连接 + return; + } + + super.exceptionCaught(ctx, cause); + } + + @Override + public void channelActive(ChannelHandlerContext ctx) throws Exception { + super.channelActive(ctx); + + FrameConnectionEvent event = null; + for (MPQClient client : clients) { + if (client.is((InetSocketAddress) ctx.channel().remoteAddress())) { + event = new FrameConnectionEvent(client.getFrame()); + client.setAddress((InetSocketAddress) ctx.channel().remoteAddress()); + client.setCtx(ctx); + break; + } + } + + if (event == null) { + Frame frame = new Frame(getJPREMain()); + MPQClient client = new MPQClient(frame, (InetSocketAddress) ctx.channel().remoteAddress(), ctx); + clients.add(client); + event = new FrameConnectionEvent(frame); + } + + event.getFrame().getPluginManager().callEvent(event); + } + + @Override + public void channelInactive(ChannelHandlerContext ctx) throws Exception { + System.out.println("[Network] RemoteClient: " + ctx.channel().remoteAddress() + " disconnected."); + + for (MPQClient client : clients) { + if (client.is((InetSocketAddress) ctx.channel().remoteAddress())) { + FrameDisconnectionEvent event = new FrameDisconnectionEvent(client.getFrame()); + client.getFrame().getPluginManager().callEvent(event); + break; + } + } + + super.channelInactive(ctx); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index a02b479c3..ada15101f 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,13 @@ 2.8.5 provided + + + + io.netty + netty-all + 4.1.38.Final + From 2f2b1751538f63cef0af7fabfb289c2b2d730faf Mon Sep 17 00:00:00 2001 From: Him188moe Date: Thu, 8 Aug 2019 21:42:58 +0800 Subject: [PATCH 2/3] update project structure --- .../net/mamoe/mirai/network/BinaryStream.java | 8 +++++++ .../mamoe/mirai/network/packet/Packet.java | 8 +++++++ .../mamoe/mirai/network/packet/PacketId.java | 11 +++++++++ .../packet/client/ClientLoginPacket.java | 14 +++++++++++ .../network/packet/client/ClientPacket.java | 24 +++++++++++++++++++ .../network/packet/server/ServerPacket.java | 23 ++++++++++++++++++ 6 files changed, 88 insertions(+) create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/BinaryStream.java create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/Packet.java create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/PacketId.java create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientLoginPacket.java create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java create mode 100644 mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.java diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/BinaryStream.java b/mirai-core/src/main/java/net/mamoe/mirai/network/BinaryStream.java new file mode 100644 index 000000000..ed862b37b --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/BinaryStream.java @@ -0,0 +1,8 @@ +package net.mamoe.mirai.network; + +/** + * @author Him188moe @ Mirai Project + */ +public class BinaryStream { + +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Packet.java b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Packet.java new file mode 100644 index 000000000..8c6fec9cb --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/Packet.java @@ -0,0 +1,8 @@ +package net.mamoe.mirai.network.packet; + +/** + * @author Him188moe @ Mirai Project + */ +public interface Packet { + +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/PacketId.java b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/PacketId.java new file mode 100644 index 000000000..c0d6ef6a9 --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/PacketId.java @@ -0,0 +1,11 @@ +package net.mamoe.mirai.network.packet; + +/** + * @author Him188moe @ Mirai Project + */ +public @interface PacketId { + /** + * 获取用于识别的包 ID + */ + int value(); +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientLoginPacket.java b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientLoginPacket.java new file mode 100644 index 000000000..c15fbfb6b --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientLoginPacket.java @@ -0,0 +1,14 @@ +package net.mamoe.mirai.network.packet.client; + +import net.mamoe.mirai.network.packet.PacketId; + +/** + * @author Him188moe @ Mirai Project + */ +@PacketId(5) +public class ClientLoginPacket extends ClientPacket { + @Override + public void encode() { + + } +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java new file mode 100644 index 000000000..700d4990f --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java @@ -0,0 +1,24 @@ +package net.mamoe.mirai.network.packet.client; + +import net.mamoe.mirai.network.packet.Packet; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; + +/** + * @author Him188moe @ Mirai Project + */ +public abstract class ClientPacket extends DataOutputStream implements Packet { + public ClientPacket() { + super(new ByteArrayOutputStream()); + } + + public long readQQ() { + + } + + /** + * Encode this packet + */ + public abstract void encode(); +} diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.java b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.java new file mode 100644 index 000000000..fb6470e5b --- /dev/null +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.java @@ -0,0 +1,23 @@ +package net.mamoe.mirai.network.packet.server; + +import net.mamoe.mirai.network.packet.Packet; +import org.jetbrains.annotations.NotNull; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.InputStream; + +/** + * @author Him188moe @ Mirai Project + */ +public abstract class ServerPacket extends DataInputStream implements Packet { + public ServerPacket(@NotNull InputStream in) { + super(in); + } + + public ServerPacket(@NotNull byte[] in) { + this(new ByteArrayInputStream(in)); + } + + public abstract void decode(); +} From bcd789ef9adb81605a59ad107e4784123477bebe Mon Sep 17 00:00:00 2001 From: Him188moe Date: Thu, 8 Aug 2019 21:52:09 +0800 Subject: [PATCH 3/3] update project structure --- .../mirai/network/packet/client/ClientPacket.java | 4 ++-- mirai-core/src/test/java/NetworkTest.java | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 mirai-core/src/test/java/NetworkTest.java diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java index 700d4990f..8dccc0620 100644 --- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java +++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.java @@ -13,8 +13,8 @@ public abstract class ClientPacket extends DataOutputStream implements Packet { super(new ByteArrayOutputStream()); } - public long readQQ() { - + protected void writeQQHex(long qq) { + this.write } /** diff --git a/mirai-core/src/test/java/NetworkTest.java b/mirai-core/src/test/java/NetworkTest.java new file mode 100644 index 000000000..31deeaed2 --- /dev/null +++ b/mirai-core/src/test/java/NetworkTest.java @@ -0,0 +1,10 @@ +/** + * @author Him188moe @ Mirai Project + */ +public class NetworkTest { + public static void main(String[] args) { + + + Long.valueOf("", 16); + } +}