From 95b858d47ce451cc92d6bffc355d984491ef77fa Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 10 May 2020 03:40:55 +0300 Subject: [PATCH] take server info and disconnect --- build.gradle | 1 + settings.gradle | 5 +- .../java/mc/server/config/NetworkModule.java | 54 ++++++++++------ .../network/impl/ChannelInitializer.java | 29 +++++++++ .../server/network/impl/NettyConstants.java | 12 ++++ .../network/impl/codec/PacketDecoder.java | 43 +++++++++++++ .../network/impl/codec/PacketEncoder.java | 24 ++++++++ .../network/impl/codec/PacketSplitter.java | 29 +++++++++ .../impl/handler/AbstractPacketHandler.java | 16 +++++ .../impl/handler/HandshakeHandler.java | 25 ++++++++ .../network/impl/handler/StatusHandler.java | 20 ++++++ .../impl/io/ByteBufNetInputStream.java | 61 +++++++++++++++++++ .../impl/io/ByteBufNetOutputStream.java | 47 ++++++++++++++ 13 files changed, 347 insertions(+), 19 deletions(-) create mode 100644 src/main/java/mc/server/network/impl/ChannelInitializer.java create mode 100644 src/main/java/mc/server/network/impl/NettyConstants.java create mode 100644 src/main/java/mc/server/network/impl/codec/PacketDecoder.java create mode 100644 src/main/java/mc/server/network/impl/codec/PacketEncoder.java create mode 100644 src/main/java/mc/server/network/impl/codec/PacketSplitter.java create mode 100644 src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java create mode 100644 src/main/java/mc/server/network/impl/handler/HandshakeHandler.java create mode 100644 src/main/java/mc/server/network/impl/handler/StatusHandler.java create mode 100644 src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java create mode 100644 src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java diff --git a/build.gradle b/build.gradle index e55d1f2..e540db7 100644 --- a/build.gradle +++ b/build.gradle @@ -41,4 +41,5 @@ dependencies { /* COMPONENTS */ implementation library.guice implementation library.netty + implementation project(':protocol') } \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 766e691..f234c19 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,4 @@ -rootProject.name = projectName \ No newline at end of file +rootProject.name = projectName + +include ':protocol' +project(':protocol').projectDir = new File(settingsDir, '../mc-protocol') \ No newline at end of file diff --git a/src/main/java/mc/server/config/NetworkModule.java b/src/main/java/mc/server/config/NetworkModule.java index f6874f8..2fd4a47 100644 --- a/src/main/java/mc/server/config/NetworkModule.java +++ b/src/main/java/mc/server/config/NetworkModule.java @@ -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 channelChannelInitializer) { + ChannelInitializer channelChannelInitializer) { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) @@ -44,20 +51,31 @@ public class NetworkModule extends AbstractModule { } @Provides - @Singleton - ChannelInitializer channelChannelInitializer(List channelHandlerList) { - return new ChannelInitializer() { - @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 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 channelHandlerMap(final Injector injector) { + final Map 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; } } diff --git a/src/main/java/mc/server/network/impl/ChannelInitializer.java b/src/main/java/mc/server/network/impl/ChannelInitializer.java new file mode 100644 index 0000000..28f1d50 --- /dev/null +++ b/src/main/java/mc/server/network/impl/ChannelInitializer.java @@ -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 { + + private final Provider> channelHandlerMapProvider; + + @Inject + public ChannelInitializer( + @Named("channelHandlerMap") Provider> channelHandlerMapProvider) { + this.channelHandlerMapProvider = channelHandlerMapProvider; + } + + @Override + protected void initChannel(SocketChannel socketChannel) { + final ChannelPipeline pipeline = socketChannel.pipeline(); + channelHandlerMapProvider.get().forEach(pipeline::addLast); + } +} diff --git a/src/main/java/mc/server/network/impl/NettyConstants.java b/src/main/java/mc/server/network/impl/NettyConstants.java new file mode 100644 index 0000000..17b8a16 --- /dev/null +++ b/src/main/java/mc/server/network/impl/NettyConstants.java @@ -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 ATTR_STATE = AttributeKey.newInstance("ATTR_STATE"); +} diff --git a/src/main/java/mc/server/network/impl/codec/PacketDecoder.java b/src/main/java/mc/server/network/impl/codec/PacketDecoder.java new file mode 100644 index 0000000..8d383af --- /dev/null +++ b/src/main/java/mc/server/network/impl/codec/PacketDecoder.java @@ -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 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); + } + } +} diff --git a/src/main/java/mc/server/network/impl/codec/PacketEncoder.java b/src/main/java/mc/server/network/impl/codec/PacketEncoder.java new file mode 100644 index 0000000..3e0fb7d --- /dev/null +++ b/src/main/java/mc/server/network/impl/codec/PacketEncoder.java @@ -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 { + + 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)); + } +} diff --git a/src/main/java/mc/server/network/impl/codec/PacketSplitter.java b/src/main/java/mc/server/network/impl/codec/PacketSplitter.java new file mode 100644 index 0000000..6589c0a --- /dev/null +++ b/src/main/java/mc/server/network/impl/codec/PacketSplitter.java @@ -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 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)); + } + } +} diff --git a/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java b/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java new file mode 100644 index 0000000..8a4da37 --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/AbstractPacketHandler.java @@ -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

extends SimpleChannelInboundHandler { + + @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; +} diff --git a/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java b/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java new file mode 100644 index 0000000..b980256 --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/HandshakeHandler.java @@ -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 { + + private final Provider 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()); + } +} diff --git a/src/main/java/mc/server/network/impl/handler/StatusHandler.java b/src/main/java/mc/server/network/impl/handler/StatusHandler.java new file mode 100644 index 0000000..5fff44b --- /dev/null +++ b/src/main/java/mc/server/network/impl/handler/StatusHandler.java @@ -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 { + + @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(); + } +} diff --git a/src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java b/src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java new file mode 100644 index 0000000..3ba8b98 --- /dev/null +++ b/src/main/java/mc/server/network/impl/io/ByteBufNetInputStream.java @@ -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(); + } +} diff --git a/src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java b/src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java new file mode 100644 index 0000000..badf014 --- /dev/null +++ b/src/main/java/mc/server/network/impl/io/ByteBufNetOutputStream.java @@ -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); + } +} +