diff --git a/protocol/src/main/java/mc/protocol/State.java b/protocol/src/main/java/mc/protocol/State.java
index 3d38333..b9b9d53 100644
--- a/protocol/src/main/java/mc/protocol/State.java
+++ b/protocol/src/main/java/mc/protocol/State.java
@@ -6,6 +6,7 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor;
import mc.protocol.packets.Packet;
import mc.protocol.packets.PacketDirection;
+import mc.protocol.packets.PingPacket;
import mc.protocol.packets.client.HandshakePacket;
import mc.protocol.packets.client.LoginStartPacket;
import mc.protocol.packets.client.StatusServerRequest;
@@ -23,9 +24,15 @@ public enum State {
),
STATUS(1,
// server bound
- ImmutableBiMap.of(0x00, StatusServerRequest.class),
+ ImmutableBiMap.of(
+ 0x00, StatusServerRequest.class,
+ 0x01, PingPacket.class
+ ),
// client bound
- ImmutableBiMap.of(0x00, StatusServerResponse.class)
+ ImmutableBiMap.of(
+ 0x00, StatusServerResponse.class,
+ 0x01, PingPacket.class
+ )
),
LOGIN(2,
// server bound
diff --git a/protocol/src/main/java/mc/protocol/packets/PingPacket.java b/protocol/src/main/java/mc/protocol/packets/PingPacket.java
new file mode 100644
index 0000000..81e0b88
--- /dev/null
+++ b/protocol/src/main/java/mc/protocol/packets/PingPacket.java
@@ -0,0 +1,41 @@
+package mc.protocol.packets;
+
+import lombok.Data;
+import mc.protocol.io.NetByteBuf;
+
+/**
+ * Пинг-пакет.
+ *
+ *
Эхо-пакет, которым проверяется качество соединения между Клиентом и Сервером.
+ *
+ * По спецификации:
+ *
+ * если Сервер не ответил Клиенту в течении 20 секунд, Клиент отключается
+ * и выдаёт ошибку "Timed out".
+ * если Клиент не отвечает Серверу в течении 30 секунд, Сервер отключает Клиента.
+ *
+ *
+ * Структура пакета
+ *
+ * | FIELD | TYPE | NOTES |
+ * |---------|------|------------------------|
+ * | Payload | Long | Любое уникальное число |
+ *
+ *
+ * @see Keep Alive
+ */
+@Data
+public class PingPacket implements Packet {
+
+ private Long payload;
+
+ @Override
+ public void readSelf(NetByteBuf netByteBuf) {
+ payload = netByteBuf.readLong();
+ }
+
+ @Override
+ public void writeSelf(NetByteBuf netByteBuf) {
+ netByteBuf.writeLong(payload);
+ }
+}
diff --git a/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java b/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java
index 6fa953e..75ebe04 100644
--- a/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java
+++ b/protocol/src/main/java/mc/protocol/packets/client/LoginStartPacket.java
@@ -4,7 +4,6 @@ import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
-import mc.protocol.State;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.Packet;
@@ -21,7 +20,6 @@ import mc.protocol.packets.Packet;
*
*
* @see Login start
- * @see State
*/
@NoArgsConstructor
@Getter
diff --git a/server/src/main/java/mc/server/di/NetworkModule.java b/server/src/main/java/mc/server/di/NetworkModule.java
index c5ca566..851566e 100644
--- a/server/src/main/java/mc/server/di/NetworkModule.java
+++ b/server/src/main/java/mc/server/di/NetworkModule.java
@@ -18,6 +18,7 @@ import mc.protocol.io.codec.ProtocolSplitter;
import mc.server.network.Server;
import mc.server.network.netty.handler.HandshakeHandler;
import mc.server.network.netty.NettyServer;
+import mc.server.network.netty.handler.KeepAliveHandler;
import mc.server.network.netty.handler.LoginHandler;
import mc.server.network.netty.handler.StatusHandler;
@@ -59,7 +60,8 @@ public class NetworkModule {
@Provides
Map provideChannelHandlerMap(
Provider statusHandlerProvider,
- Provider loginHandlerProvider
+ Provider loginHandlerProvider,
+ Provider keepAliveHandlerProvider
) {
Map map = new LinkedHashMap<>();
@@ -67,7 +69,8 @@ public class NetworkModule {
map.put("protocol_splitter", new ProtocolSplitter());
map.put("protocol_decoder", new ProtocolDecoder(true));
map.put("protocol_encoder", new ProtocolEncoder());
- map.put("handshake_handler", new HandshakeHandler(statusHandlerProvider, loginHandlerProvider));
+ map.put("handshake_handler", new HandshakeHandler(
+ statusHandlerProvider, loginHandlerProvider, keepAliveHandlerProvider));
return map;
}
@@ -81,4 +84,9 @@ public class NetworkModule {
LoginHandler provideLoginHandler() {
return new LoginHandler();
}
+
+ @Provides
+ KeepAliveHandler provideKeepAliveHandler() {
+ return new KeepAliveHandler();
+ }
}
diff --git a/server/src/main/java/mc/server/network/netty/handler/HandshakeHandler.java b/server/src/main/java/mc/server/network/netty/handler/HandshakeHandler.java
index 5f31d3e..02b19e0 100644
--- a/server/src/main/java/mc/server/network/netty/handler/HandshakeHandler.java
+++ b/server/src/main/java/mc/server/network/netty/handler/HandshakeHandler.java
@@ -15,6 +15,7 @@ public class HandshakeHandler extends AbstractPacketHandler {
private final Provider statusHandlerProvider;
private final Provider loginHandlerProvider;
+ private final Provider keepAliveHandlerProvider;
@Override
protected void channelRead1(ChannelHandlerContext ctx, HandshakePacket packet) {
@@ -24,6 +25,7 @@ public class HandshakeHandler extends AbstractPacketHandler {
if (State.STATUS == packet.getNextState()) {
ctx.pipeline().replace("handshake_handler", "status_handler", statusHandlerProvider.get());
+ ctx.pipeline().addAfter("status_handler", "keepalive_handler", keepAliveHandlerProvider.get());
} else if (State.LOGIN == packet.getNextState()) {
ctx.channel().pipeline().replace("handshake_handler", "login_handler", loginHandlerProvider.get());
}
diff --git a/server/src/main/java/mc/server/network/netty/handler/KeepAliveHandler.java b/server/src/main/java/mc/server/network/netty/handler/KeepAliveHandler.java
new file mode 100644
index 0000000..ea69c2c
--- /dev/null
+++ b/server/src/main/java/mc/server/network/netty/handler/KeepAliveHandler.java
@@ -0,0 +1,16 @@
+package mc.server.network.netty.handler;
+
+import io.netty.channel.ChannelHandlerContext;
+import lombok.extern.slf4j.Slf4j;
+import mc.protocol.packets.PingPacket;
+
+@Slf4j
+public class KeepAliveHandler extends AbstractPacketHandler {
+
+ @Override
+ protected void channelRead1(ChannelHandlerContext ctx, PingPacket packet) {
+ log.info("{}", packet);
+
+ ctx.writeAndFlush(packet).channel().disconnect();
+ }
+}
diff --git a/server/src/main/java/mc/server/network/netty/handler/StatusHandler.java b/server/src/main/java/mc/server/network/netty/handler/StatusHandler.java
index 0628875..2fbcfe5 100644
--- a/server/src/main/java/mc/server/network/netty/handler/StatusHandler.java
+++ b/server/src/main/java/mc/server/network/netty/handler/StatusHandler.java
@@ -28,6 +28,6 @@ public class StatusHandler extends AbstractPacketHandler {
" }\n" +
"}");
- ctx.channel().writeAndFlush(response).channel().disconnect();
+ ctx.channel().writeAndFlush(response);
}
}