mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-19 07:38:32 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
2eccc978f0
@ -38,6 +38,13 @@
|
|||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package net.mamoe.mirai.network;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Him188moe @ Mirai Project
|
||||||
|
*/
|
||||||
|
public class BinaryStream {
|
||||||
|
|
||||||
|
}
|
@ -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<SocketChannel>() {
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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<byte[]> {
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package net.mamoe.mirai.network.packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Him188moe @ Mirai Project
|
||||||
|
*/
|
||||||
|
public interface Packet {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package net.mamoe.mirai.network.packet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Him188moe @ Mirai Project
|
||||||
|
*/
|
||||||
|
public @interface PacketId {
|
||||||
|
/**
|
||||||
|
* 获取用于识别的包 ID
|
||||||
|
*/
|
||||||
|
int value();
|
||||||
|
}
|
@ -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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeQQHex(long qq) {
|
||||||
|
this.write
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encode this packet
|
||||||
|
*/
|
||||||
|
public abstract void encode();
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
10
mirai-core/src/test/java/NetworkTest.java
Normal file
10
mirai-core/src/test/java/NetworkTest.java
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* @author Him188moe @ Mirai Project
|
||||||
|
*/
|
||||||
|
public class NetworkTest {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
|
||||||
|
Long.valueOf("", 16);
|
||||||
|
}
|
||||||
|
}
|
7
pom.xml
7
pom.xml
@ -92,6 +92,13 @@
|
|||||||
<version>2.8.5</version>
|
<version>2.8.5</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.1.38.Final</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user