take server info and disconnect
This commit is contained in:
@@ -41,4 +41,5 @@ dependencies {
|
||||
/* COMPONENTS */
|
||||
implementation library.guice
|
||||
implementation library.netty
|
||||
implementation project(':protocol')
|
||||
}
|
||||
@@ -1 +1,4 @@
|
||||
rootProject.name = projectName
|
||||
|
||||
include ':protocol'
|
||||
project(':protocol').projectDir = new File(settingsDir, '../mc-protocol')
|
||||
@@ -1,24 +1,31 @@
|
||||
package mc.server.config;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import com.google.inject.name.Names;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
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.logging.LoggingHandler;
|
||||
import mc.protocol.PacketDirection;
|
||||
import mc.protocol.io.coder.ProtocolDecoder;
|
||||
import mc.protocol.io.coder.ProtocolEncoder;
|
||||
import mc.protocol.io.coder.ProtocolSplitter;
|
||||
import mc.server.network.Server;
|
||||
import mc.server.network.impl.ChannelInitializer;
|
||||
import mc.server.network.impl.NettyServer;
|
||||
import mc.server.network.impl.codec.PacketDecoder;
|
||||
import mc.server.network.impl.codec.PacketEncoder;
|
||||
import mc.server.network.impl.codec.PacketSplitter;
|
||||
import mc.server.network.impl.handler.HandshakeHandler;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class NetworkModule extends AbstractModule {
|
||||
|
||||
@@ -33,7 +40,7 @@ public class NetworkModule extends AbstractModule {
|
||||
@Singleton
|
||||
ServerBootstrap serverBootstrap(@Named("bossGroup") EventLoopGroup bossGroup,
|
||||
@Named("workerGroup") EventLoopGroup workerGroup,
|
||||
ChannelInitializer<SocketChannel> channelChannelInitializer) {
|
||||
ChannelInitializer channelChannelInitializer) {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
|
||||
bootstrap.group(bossGroup, workerGroup)
|
||||
@@ -44,20 +51,31 @@ public class NetworkModule extends AbstractModule {
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ChannelInitializer<SocketChannel> channelChannelInitializer(List<ChannelHandler> channelHandlerList) {
|
||||
return new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) {
|
||||
final ChannelPipeline pipeline = socketChannel.pipeline();
|
||||
channelHandlerList.forEach(pipeline::addLast);
|
||||
}
|
||||
};
|
||||
PacketSplitter packetSplitter() {
|
||||
return new PacketSplitter(new ProtocolSplitter());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
List<ChannelHandler> channelHandlerList() {
|
||||
return Collections.singletonList(new LoggingHandler());
|
||||
PacketDecoder packetDecoder() {
|
||||
return new PacketDecoder(new ProtocolDecoder(PacketDirection.SERVER_BOUND));
|
||||
}
|
||||
|
||||
@Provides
|
||||
PacketEncoder packetEncoder() {
|
||||
return new PacketEncoder(new ProtocolEncoder(PacketDirection.CLIENT_BOUND));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("channelHandlerMap")
|
||||
Map<String, ChannelHandler> channelHandlerMap(final Injector injector) {
|
||||
final Map<String, ChannelHandler> map = new HashMap<>();
|
||||
|
||||
map.put("logger", injector.getInstance(LoggingHandler.class));
|
||||
map.put("packet_splitter", injector.getInstance(PacketSplitter.class));
|
||||
map.put("packet_decoder", injector.getInstance(PacketDecoder.class));
|
||||
map.put("packet_encoder", injector.getInstance(PacketEncoder.class));
|
||||
map.put("handshake_handler", injector.getInstance(HandshakeHandler.class));
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
29
src/main/java/mc/server/network/impl/ChannelInitializer.java
Normal file
29
src/main/java/mc/server/network/impl/ChannelInitializer.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package mc.server.network.impl;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.name.Named;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Singleton
|
||||
public class ChannelInitializer extends io.netty.channel.ChannelInitializer<SocketChannel> {
|
||||
|
||||
private final Provider<Map<String, ChannelHandler>> channelHandlerMapProvider;
|
||||
|
||||
@Inject
|
||||
public ChannelInitializer(
|
||||
@Named("channelHandlerMap") Provider<Map<String, ChannelHandler>> channelHandlerMapProvider) {
|
||||
this.channelHandlerMapProvider = channelHandlerMapProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel socketChannel) {
|
||||
final ChannelPipeline pipeline = socketChannel.pipeline();
|
||||
channelHandlerMapProvider.get().forEach(pipeline::addLast);
|
||||
}
|
||||
}
|
||||
12
src/main/java/mc/server/network/impl/NettyConstants.java
Normal file
12
src/main/java/mc/server/network/impl/NettyConstants.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package mc.server.network.impl;
|
||||
|
||||
import io.netty.util.AttributeKey;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import mc.protocol.State;
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class NettyConstants {
|
||||
|
||||
public static final AttributeKey<State> ATTR_STATE = AttributeKey.newInstance("ATTR_STATE");
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package mc.server.network.impl.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.Packet;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.io.coder.ProtocolDecoder;
|
||||
import mc.server.network.impl.io.ByteBufNetInputStream;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static mc.server.network.impl.NettyConstants.ATTR_STATE;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PacketDecoder extends ByteToMessageDecoder {
|
||||
|
||||
private final ProtocolDecoder protocolDecoder;
|
||||
|
||||
@Override
|
||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.channel().attr(ATTR_STATE).set(State.HANDSHAKING);
|
||||
super.channelActive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||
ctx.channel().attr(ATTR_STATE).set(null);
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
final State state = Objects.requireNonNull(ctx.channel().attr(ATTR_STATE).get());
|
||||
|
||||
final Packet packet = protocolDecoder.decode(state, new ByteBufNetInputStream(in));
|
||||
if (packet != null) {
|
||||
out.add(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package mc.server.network.impl.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.Packet;
|
||||
import mc.protocol.State;
|
||||
import mc.protocol.io.coder.ProtocolEncoder;
|
||||
import mc.server.network.impl.io.ByteBufNetOutputStream;
|
||||
|
||||
import static mc.server.network.impl.NettyConstants.ATTR_STATE;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PacketEncoder extends MessageToByteEncoder<Packet> {
|
||||
|
||||
private final ProtocolEncoder protocolEncoder;
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf out) {
|
||||
final State state = ctx.channel().attr(ATTR_STATE).get();
|
||||
protocolEncoder.encode(state, packet, new ByteBufNetOutputStream(out));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package mc.server.network.impl.codec;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.io.NetInputStream;
|
||||
import mc.protocol.io.coder.ProtocolSplitter;
|
||||
import mc.server.network.impl.io.ByteBufNetInputStream;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class PacketSplitter extends ByteToMessageDecoder {
|
||||
|
||||
private final ProtocolSplitter protocolSplitter;
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
final NetInputStream netInputStream = protocolSplitter.split(new ByteBufNetInputStream(in));
|
||||
|
||||
if (netInputStream != null) {
|
||||
byte[] buff = new byte[netInputStream.readableBytes()];
|
||||
netInputStream.readBytes(buff);
|
||||
out.add(Unpooled.wrappedBuffer(buff));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package mc.server.network.impl.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import mc.protocol.Packet;
|
||||
|
||||
public abstract class AbstractPacketHandler<P extends Packet> extends SimpleChannelInboundHandler<Packet> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Packet msg) throws Exception {
|
||||
channelRead1(ctx, (P) msg);
|
||||
}
|
||||
|
||||
protected abstract void channelRead1(ChannelHandlerContext ctx, P packet) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package mc.server.network.impl.handler;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.handshake.client.HandshakePacket;
|
||||
|
||||
import static mc.server.network.impl.NettyConstants.ATTR_STATE;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
|
||||
public class HandshakeHandler extends AbstractPacketHandler<HandshakePacket> {
|
||||
|
||||
private final Provider<StatusHandler> statusHandlerProvider;
|
||||
|
||||
@Override
|
||||
protected void channelRead1(ChannelHandlerContext ctx, HandshakePacket packet) {
|
||||
log.info("{}", packet);
|
||||
|
||||
ctx.channel().attr(ATTR_STATE).set(packet.getNextState());
|
||||
ctx.pipeline().replace("handshake_handler", "status_handler", statusHandlerProvider.get());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package mc.server.network.impl.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import mc.protocol.status.client.StatusServerRequest;
|
||||
import mc.protocol.status.server.StatusServerResponse;
|
||||
|
||||
@Slf4j
|
||||
public class StatusHandler extends AbstractPacketHandler<StatusServerRequest> {
|
||||
|
||||
@Override
|
||||
protected void channelRead1(ChannelHandlerContext ctx, StatusServerRequest packet) {
|
||||
log.info("{}", packet);
|
||||
|
||||
StatusServerResponse response = new StatusServerResponse();
|
||||
response.setInfo("some info server text");
|
||||
|
||||
ctx.channel().writeAndFlush(response).channel().disconnect();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package mc.server.network.impl.io;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.io.NetInputStream;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ByteBufNetInputStream extends NetInputStream {
|
||||
|
||||
private final ByteBuf byteBuf;
|
||||
|
||||
@Override
|
||||
public void markReadIndex() {
|
||||
byteBuf.markReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetReadIndex() {
|
||||
byteBuf.resetReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readableBytes() {
|
||||
return byteBuf.readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() {
|
||||
return byteBuf.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readBytes(byte[] buffer, int offset, int lengtn) {
|
||||
return byteBuf.readBytes(buffer, offset, lengtn).readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readShort() {
|
||||
return byteBuf.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() {
|
||||
return byteBuf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() {
|
||||
return byteBuf.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat() {
|
||||
return byteBuf.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() {
|
||||
return byteBuf.readDouble();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package mc.server.network.impl.io;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import mc.protocol.io.NetOutputStream;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ByteBufNetOutputStream extends NetOutputStream {
|
||||
|
||||
private final ByteBuf byteBuf;
|
||||
|
||||
@Override
|
||||
public void writeByte(int value) {
|
||||
byteBuf.writeByte(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(byte[] buffer, int offset, int lengtn) {
|
||||
byteBuf.writeBytes(buffer, offset, lengtn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShort(int value) {
|
||||
byteBuf.writeShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(int value) {
|
||||
byteBuf.writeInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLong(long value) {
|
||||
byteBuf.writeLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFloat(float value) {
|
||||
byteBuf.writeFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDouble(double value) {
|
||||
byteBuf.writeDouble(value);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user