From 14f5358e8b84c012ea65390a908d30808dea96b4 Mon Sep 17 00:00:00 2001 From: godotg Date: Mon, 25 Sep 2023 23:14:33 +0800 Subject: [PATCH] feat[zfoo]: compatible field of inside protocol class --- .../zfoo/protocol/buffer/ByteBufUtils.java | 2 +- .../registration/ProtocolAnalysis.java | 8 +- .../registration/ProtocolRegistration.java | 80 ++++++++++++++++--- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java b/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java index 20b3791a..f5652f55 100644 --- a/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java +++ b/protocol/src/main/java/com/zfoo/protocol/buffer/ByteBufUtils.java @@ -168,7 +168,7 @@ public abstract class ByteBufUtils { } - private static int writeIntCount(int value) { + public static int writeIntCount(int value) { value = (value << 1) ^ (value >> 31); if (value >>> 7 == 0) { diff --git a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java index d3ba0f35..13b116b0 100644 --- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java +++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolAnalysis.java @@ -448,13 +448,7 @@ public class ProtocolAnalysis { } ReflectionUtils.makeAccessible(constructor); - var protocol = new ProtocolRegistration(); - protocol.setId(protocolId); - protocol.setConstructor(constructor); - protocol.setFields(ArrayUtils.listToArray(fields, Field.class)); - protocol.setFieldRegistrations(ArrayUtils.listToArray(registrationList, IFieldRegistration.class)); - protocol.setModule(module.getId()); - return protocol; + return new ProtocolRegistration(protocolId, module.getId(), constructor, ArrayUtils.listToArray(fields, Field.class), ArrayUtils.listToArray(registrationList, IFieldRegistration.class)); } catch (Exception e) { throw new RuntimeException(StringUtils.format("解析协议[class:{}]异常", clazz), e); } diff --git a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java index ffa04d0a..6546f82d 100644 --- a/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java +++ b/protocol/src/main/java/com/zfoo/protocol/registration/ProtocolRegistration.java @@ -19,9 +19,11 @@ import com.zfoo.protocol.registration.field.IFieldRegistration; import com.zfoo.protocol.serializer.reflect.ISerializer; import com.zfoo.protocol.util.ReflectionUtils; import io.netty.buffer.ByteBuf; +import io.netty.util.ReferenceCountUtil; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.util.Arrays; /** * @author godotg @@ -38,8 +40,19 @@ public class ProtocolRegistration implements IProtocolRegistration { */ private IFieldRegistration[] fieldRegistrations; - public ProtocolRegistration() { + // 兼容相关 + private boolean compatible; + private int predictionLength; + public ProtocolRegistration(short id, byte module, Constructor constructor, Field[] fields, IFieldRegistration[] fieldRegistrations) { + this.id = id; + this.module = module; + this.constructor = constructor; + this.fields = fields; + this.fieldRegistrations = fieldRegistrations; + + this.compatible = Arrays.stream(fields).anyMatch(it -> it.isAnnotationPresent(Compatible.class)); + this.predictionLength = 128; } @Override @@ -58,41 +71,86 @@ public class ProtocolRegistration implements IProtocolRegistration { } @Override - public void write(ByteBuf buffer, Object packet) { + public void write(ByteBuf byteBuf, Object packet) { if (packet == null) { - ByteBufUtils.writeBoolean(buffer, false); + ByteBufUtils.writeByte(byteBuf, (byte) 0); return; } - ByteBufUtils.writeBoolean(buffer, true); + if (compatible) { + byteBuf.markWriterIndex(); + ByteBufUtils.writeInt(byteBuf, predictionLength); + } else { + ByteBufUtils.writeInt(byteBuf, -1); + } + var beforeWriteIndex = byteBuf.writerIndex(); for (int i = 0, length = fields.length; i < length; i++) { Field field = fields[i]; IFieldRegistration packetFieldRegistration = fieldRegistrations[i]; ISerializer serializer = packetFieldRegistration.serializer(); Object fieldValue = ReflectionUtils.getField(field, packet); - serializer.writeObject(buffer, fieldValue, packetFieldRegistration); + serializer.writeObject(byteBuf, fieldValue, packetFieldRegistration); + } + + if (compatible) { + // 因为写入的是可变长的int,如果预留的位置过多,则清除多余的位置 + var currentWriteIndex = byteBuf.writerIndex(); + var length = currentWriteIndex - beforeWriteIndex; + var lengthCount = ByteBufUtils.writeIntCount(length); + var padding = lengthCount - ByteBufUtils.writeIntCount(predictionLength); + if (padding == 0) { + byteBuf.resetWriterIndex(); + ByteBufUtils.writeInt(byteBuf, length); + byteBuf.writerIndex(currentWriteIndex); + } else if (padding < 0) { + var retainedByteBuf = byteBuf.retainedSlice(currentWriteIndex - length, length); + byteBuf.resetWriterIndex(); + ByteBufUtils.writeInt(byteBuf, length); + byteBuf.writeBytes(retainedByteBuf); + ReferenceCountUtil.release(retainedByteBuf); + } else { + var retainedByteBuf = byteBuf.retainedSlice(currentWriteIndex - length, length); + var bytes = ByteBufUtils.readAllBytes(retainedByteBuf); + byteBuf.resetWriterIndex(); + ByteBufUtils.writeInt(byteBuf, length); + byteBuf.writeBytes(bytes); + ReferenceCountUtil.release(retainedByteBuf); + } } } @Override - public Object read(ByteBuf buffer) { - if (!ByteBufUtils.readBoolean(buffer)) { + public Object read(ByteBuf byteBuf) { + var length = ByteBufUtils.readInt(byteBuf); + if (length == 0) { return null; } Object object = ReflectionUtils.newInstance(constructor); - for (int i = 0, length = fields.length; i < length; i++) { + var readIndex = byteBuf.readerIndex(); + for (int i = 0, j = fields.length; i < j; i++) { Field field = fields[i]; // 协议向后兼容 - if (field.isAnnotationPresent(Compatible.class) && !buffer.isReadable()) { - break; + if (field.isAnnotationPresent(Compatible.class)) { + if (length == -1) { + break; + } else { + if (byteBuf.readerIndex() - readIndex >= length) { + break; + } + } } IFieldRegistration packetFieldRegistration = fieldRegistrations[i]; ISerializer serializer = packetFieldRegistration.serializer(); - Object fieldValue = serializer.readObject(buffer, packetFieldRegistration); + Object fieldValue = serializer.readObject(byteBuf, packetFieldRegistration); ReflectionUtils.setField(field, object, fieldValue); } + + if (length > 0 && byteBuf.readInt() - readIndex < length) { + byteBuf.readerIndex(readIndex + length); + } + return object; }