Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/main/java/cn/rukkit/network/core/packet/Packet.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2020-2022 RukkitDev Team and contributors.
*
* This project uses GNU Affero General Public License v3.0.You can find this license in the following link.
* 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看:
*
* https://github.com/RukkitDev/Rukkit/blob/master/LICENSE
*/

package cn.rukkit.network.core.packet;

/**
* A length-prefixed game packet payload and its protocol type.
*
* <p>The wire format is a four-byte payload length, followed by a four-byte
* packet type and the payload bytes. The class intentionally keeps the fields
* mutable because packet builders in the existing network stack fill the
* payload after constructing the packet.</p>
*/
public class Packet {
/** Sentinel used when the framed protocol should not impose a payload limit. */
public static final int NO_MAX_FRAME_LENGTH = Integer.MAX_VALUE;

/** The first migration stage deliberately leaves the payload size unlimited. */
public static final int DEFAULT_MAX_FRAME_LENGTH = NO_MAX_FRAME_LENGTH;

public byte[] bytes;
public int type;

public Packet(int type) {
this.type = type;
}

public Packet(int type, byte[] bytes) {
this.type = type;
this.bytes = bytes;
}

public Packet() {
this(0);
}
}
74 changes: 74 additions & 0 deletions src/main/java/cn/rukkit/network/core/packet/PacketDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2020-2022 RukkitDev Team and contributors.
*
* This project uses GNU Affero General Public License v3.0.You can find this license in the following link.
* 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看:
*
* https://github.com/RukkitDev/Rukkit/blob/master/LICENSE
*/

package cn.rukkit.network.core.packet;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.CorruptedFrameException;
import io.netty.handler.codec.TooLongFrameException;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Decodes the length-prefixed packet wire format. */
public class PacketDecoder extends ByteToMessageDecoder {
private static final int HEADER_SIZE = Integer.BYTES * 2;
private static final Logger LOG = LoggerFactory.getLogger(PacketDecoder.class);

private final int maxFrameLength;

public PacketDecoder() {
this(Packet.DEFAULT_MAX_FRAME_LENGTH);
}

public PacketDecoder(int maxFrameLength) {
if (maxFrameLength <= 0) {
throw new IllegalArgumentException("maxFrameLength must be positive");
}
this.maxFrameLength = maxFrameLength;
}

public int getMaxFrameLength() {
return maxFrameLength;
}

@Override
protected void decode(ChannelHandlerContext context, ByteBuf in, List<Object> out) {
if (in.readableBytes() < HEADER_SIZE) {
return;
}

in.markReaderIndex();
int length = in.readInt();
int type = in.readInt();

if (length < 0) {
throw new CorruptedFrameException("negative packet payload length: " + length);
}
if (length > maxFrameLength) {
throw new TooLongFrameException(
"packet payload length " + length + " exceeds " + maxFrameLength);
}
if (in.readableBytes() < length) {
in.resetReaderIndex();
return;
}

byte[] bytes = new byte[length];
in.readBytes(bytes);

Packet packet = new Packet(type, bytes);
if (LOG.isTraceEnabled() && (type != PacketType.TICK || length > 20)) {
LOG.trace("Received packet type={} size={}", type, length);
}
out.add(packet);
}
}
60 changes: 60 additions & 0 deletions src/main/java/cn/rukkit/network/core/packet/PacketEncoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright 2020-2022 RukkitDev Team and contributors.
*
* This project uses GNU Affero General Public License v3.0.You can find this license in the following link.
* 本项目使用 GNU Affero General Public License v3.0 许可证,你可以在下方链接查看:
*
* https://github.com/RukkitDev/Rukkit/blob/master/LICENSE
*/

package cn.rukkit.network.core.packet;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.EncoderException;
import io.netty.handler.codec.MessageToByteEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Encodes a {@link Packet} as length, type and payload. */
public class PacketEncoder extends MessageToByteEncoder<Packet> {
private static final Logger LOG = LoggerFactory.getLogger(PacketEncoder.class);

private final int maxFrameLength;

public PacketEncoder() {
this(Packet.DEFAULT_MAX_FRAME_LENGTH);
}

public PacketEncoder(int maxFrameLength) {
if (maxFrameLength <= 0) {
throw new IllegalArgumentException("maxFrameLength must be positive");
}
this.maxFrameLength = maxFrameLength;
}

public int getMaxFrameLength() {
return maxFrameLength;
}

@Override
protected void encode(ChannelHandlerContext context, Packet packet, ByteBuf out) {
if (packet == null) {
throw new EncoderException("packet must not be null");
}
if (packet.bytes == null) {
throw new EncoderException("packet payload must not be null");
}
if (packet.bytes.length > maxFrameLength) {
throw new EncoderException("packet payload exceeds maxFrameLength: " + packet.bytes.length);
}

if (LOG.isTraceEnabled() && (packet.type != PacketType.TICK || packet.bytes.length > 20)) {
LOG.trace("Sending packet type={} size={}", packet.type, packet.bytes.length);
}

out.writeInt(packet.bytes.length);
out.writeInt(packet.type);
out.writeBytes(packet.bytes);
}
}
50 changes: 50 additions & 0 deletions src/main/java/cn/rukkit/network/core/packet/PacketType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package cn.rukkit.network.core.packet;

/** Packet type identifiers used by the game protocol. */
public final class PacketType {
private PacketType() {
}

// Server commands
public static final int REGISTER_CONNECTION = 161;
public static final int TEAM_LIST = 115;
public static final int HEART_BEAT = 108;
public static final int SEND_CHAT = 141;
public static final int SERVER_INFO = 106;
public static final int START_GAME = 120;
public static final int QUESTION = 117;
public static final int QUESTION_RESPONCE = 118;
public static final int QUESTION_RESPONSE = QUESTION_RESPONCE;
public static final int KICK = 150;
public static final int RETURN_TO_BATTLEROOM = 122;

// Client commands
public static final int PREREGISTER_CONNECTION = 160;
public static final int HEART_BEAT_RESPONSE = 109;
public static final int ADD_CHAT = 140;
public static final int PLAYER_INFO = 110;
public static final int DISCONNECT = 111;
public static final int READY = 112;

// Game commands
public static final int ADD_GAMECOMMAND = 20;
public static final int TICK = 10;
public static final int SYNC_CHECKSUM = 30;
public static final int SYNC_CHECKSUM_RESPONCE = 31;
public static final int SYNC_CHECKSUM_RESPONSE = SYNC_CHECKSUM_RESPONCE;
public static final int SYNC = 35;

// Relay commands
public static final int RELAY_117 = 117;
public static final int RELAY_118_117_RETURN = 118;
public static final int RELAY_POW = 151;
public static final int RELAY_POW_RECEIVE = 152;
public static final int RELAY_VERSION_INFO = 163;
public static final int RELAY_BECOME_SERVER = 170;
public static final int FORWARD_CLIENT_ADD = 172;
public static final int FORWARD_CLIENT_REMOVE = 173;
public static final int PACKET_FORWARD_CLIENT_FROM = 174;
public static final int PACKET_FORWARD_CLIENT_TO = 175;
public static final int PACKET_FORWARD_CLIENT_TO_REPEATED = 176;
public static final int PACKET_RECONNECT_TO = 178;
}
Loading
Loading