|
|
|
@ -1,18 +1,17 @@ |
|
|
|
package net.sopod.soim.data.serialize; |
|
|
|
package net.sopod.soim.data.serialize; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.google.protobuf.InvalidProtocolBufferException; |
|
|
|
import com.google.protobuf.MessageLite; |
|
|
|
import com.google.protobuf.MessageLite; |
|
|
|
import io.netty.buffer.ByteBuf; |
|
|
|
import io.netty.buffer.ByteBuf; |
|
|
|
import io.netty.channel.ChannelHandlerContext; |
|
|
|
import io.netty.channel.ChannelHandlerContext; |
|
|
|
import io.netty.channel.CombinedChannelDuplexHandler; |
|
|
|
|
|
|
|
import io.netty.handler.codec.ByteToMessageDecoder; |
|
|
|
import io.netty.handler.codec.ByteToMessageDecoder; |
|
|
|
import io.netty.handler.codec.MessageToByteEncoder; |
|
|
|
import io.netty.handler.codec.MessageToByteEncoder; |
|
|
|
import io.netty.handler.codec.MessageToMessageEncoder; |
|
|
|
import net.sopod.soim.common.dubbo.exception.ConvertException; |
|
|
|
|
|
|
|
import net.sopod.soim.common.dubbo.exception.SoimException; |
|
|
|
import net.sopod.soim.data.proto.ProtoMessageManager; |
|
|
|
import net.sopod.soim.data.proto.ProtoMessageManager; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Type; |
|
|
|
|
|
|
|
import java.util.Arrays; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -21,90 +20,57 @@ import java.util.List; |
|
|
|
* @author tmy |
|
|
|
* @author tmy |
|
|
|
* @date 2022-03-28 11:29 |
|
|
|
* @date 2022-03-28 11:29 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class ImMessageCodec //extends MessageToMessageCodec<ByteBuf, MessageLite> {
|
|
|
|
public class ImMessageCodec { |
|
|
|
extends CombinedChannelDuplexHandler<ImMessageCodec.ProtoMsgDecoder, ImMessageCodec.ProtoMsgEncoder> { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ImMessageCodec.class); |
|
|
|
private static final Logger logger = LoggerFactory.getLogger(ImMessageCodec.class); |
|
|
|
|
|
|
|
|
|
|
|
public ImMessageCodec() { |
|
|
|
|
|
|
|
super(new ProtoMsgDecoder(), new ProtoMsgEncoder()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static class ImMessageDecoder extends ByteToMessageDecoder { |
|
|
|
public static class ImMessageDecoder extends ByteToMessageDecoder { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception { |
|
|
|
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception { |
|
|
|
ImMessage message = ImMessage.read(byteBuf); |
|
|
|
ImMessage imMessage = ImMessageCodec.decodeImMessage(byteBuf); |
|
|
|
boolean isMagicError; |
|
|
|
out.add(imMessage); |
|
|
|
if ((isMagicError = (message == ImMessage.MAGIC_ERROR)) |
|
|
|
|
|
|
|
|| message == ImMessage.PROTOCOL_ERROR) { |
|
|
|
|
|
|
|
logger.warn("decode im message error: {}, remote={}, closing channel.", |
|
|
|
|
|
|
|
isMagicError ? "MagicError" : "ProtocolError", |
|
|
|
|
|
|
|
ctx.channel().remoteAddress()); |
|
|
|
|
|
|
|
ctx.channel().close(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 解码 protobuf 消息体
|
|
|
|
|
|
|
|
int serviceNo = message.getServiceNo(); |
|
|
|
|
|
|
|
byte[] protoByte = message.getBody(); |
|
|
|
|
|
|
|
MessageLite protoClass = ProtoMessageManager.getProtoInstance(serviceNo); |
|
|
|
|
|
|
|
MessageLite protoMsg = protoClass.getParserForType().parseFrom(protoByte); |
|
|
|
|
|
|
|
message.setDecodeBody(protoMsg); |
|
|
|
|
|
|
|
out.add(message); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static class ProtoMsgDecoder extends ByteToMessageDecoder { |
|
|
|
public static class ImMessage2ByteEncoder extends MessageToByteEncoder<ImMessage> { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception { |
|
|
|
protected void encode(ChannelHandlerContext ctx, ImMessage imMessage, ByteBuf byteBuf) throws Exception { |
|
|
|
ImMessage message = ImMessage.read(byteBuf); |
|
|
|
imMessage.write(byteBuf); |
|
|
|
boolean isMagicError; |
|
|
|
|
|
|
|
if ((isMagicError = (message == ImMessage.MAGIC_ERROR)) |
|
|
|
|
|
|
|
|| message == ImMessage.PROTOCOL_ERROR) { |
|
|
|
|
|
|
|
logger.warn("decode im message error: {}, remote={}, closing channel.", |
|
|
|
|
|
|
|
isMagicError ? "MagicError" : "ProtocolError", |
|
|
|
|
|
|
|
ctx.channel().remoteAddress()); |
|
|
|
|
|
|
|
ctx.channel().close(); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 解码 protobuf 消息体
|
|
|
|
|
|
|
|
int serviceNo = message.getServiceNo(); |
|
|
|
|
|
|
|
// message.getSerialNo()
|
|
|
|
|
|
|
|
byte[] protoByte = message.getBody(); |
|
|
|
|
|
|
|
MessageLite protoClass = ProtoMessageManager.getProtoInstance(serviceNo); |
|
|
|
|
|
|
|
MessageLite protoMsg = protoClass.getParserForType().parseFrom(protoByte); |
|
|
|
|
|
|
|
list.add(protoMsg); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static class ProtoMsg2ImMessageEncoder extends MessageToMessageEncoder<MessageLite> { |
|
|
|
public static ImMessage decodeImMessage(ByteBuf byteBuf) { |
|
|
|
@Override |
|
|
|
ImMessage imMessage = ImMessage.read(byteBuf); |
|
|
|
protected void encode(ChannelHandlerContext ctx, MessageLite message, List<Object> out) throws Exception { |
|
|
|
boolean isMagicError; |
|
|
|
Integer serialNo = ProtoMessageManager.getSerialNo(message.getClass()); |
|
|
|
if ((isMagicError = (imMessage == ImMessage.MAGIC_ERROR)) |
|
|
|
// TODO unknow class serialNo
|
|
|
|
|| imMessage == ImMessage.PROTOCOL_ERROR) { |
|
|
|
ImMessage imMessage = new ImMessage() |
|
|
|
throw new ConvertException("ImMessage解码错误"); |
|
|
|
.setServiceNo(serialNo) |
|
|
|
|
|
|
|
.setBody(message.toByteArray()); |
|
|
|
|
|
|
|
out.add(imMessage); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 解码 protobuf 消息体
|
|
|
|
|
|
|
|
int serviceNo = imMessage.getServiceNo(); |
|
|
|
|
|
|
|
byte[] protoByte = imMessage.getBody(); |
|
|
|
|
|
|
|
MessageLite protoClass = ProtoMessageManager.getDefaultInstance(serviceNo); |
|
|
|
|
|
|
|
if (protoClass == null) { |
|
|
|
|
|
|
|
throw new SoimException(String.format("不支持的消息编号: %d", serviceNo)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
MessageLite protoMsg; |
|
|
|
public static class ImMessage2ByteEncoder extends MessageToByteEncoder<ImMessage> { |
|
|
|
try { |
|
|
|
@Override |
|
|
|
protoMsg = protoClass.getParserForType().parseFrom(protoByte); |
|
|
|
protected void encode(ChannelHandlerContext ctx, ImMessage imMessage, ByteBuf out) throws Exception { |
|
|
|
} catch (InvalidProtocolBufferException e) { |
|
|
|
imMessage.write(out); |
|
|
|
throw new ConvertException("ImMessage消息体Protobuf解码错误: " + e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
imMessage.setDecodeBody(protoMsg); |
|
|
|
|
|
|
|
return imMessage; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static class ProtoMsgEncoder extends MessageToByteEncoder<MessageLite> { |
|
|
|
public static ImMessage encodeImProto(MessageLite message) { |
|
|
|
@Override |
|
|
|
|
|
|
|
protected void encode(ChannelHandlerContext ctx, MessageLite message, ByteBuf byteBuf) throws Exception { |
|
|
|
|
|
|
|
Integer serialNo = ProtoMessageManager.getSerialNo(message.getClass()); |
|
|
|
Integer serialNo = ProtoMessageManager.getSerialNo(message.getClass()); |
|
|
|
// TODO unknow class serialNo
|
|
|
|
if (serialNo == null) { |
|
|
|
ImMessage imMessage = new ImMessage() |
|
|
|
throw new SoimException("未知的Protobuf消息类型:" + message.getClass()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return new ImMessage() |
|
|
|
.setServiceNo(serialNo) |
|
|
|
.setServiceNo(serialNo) |
|
|
|
.setBody(message.toByteArray()); |
|
|
|
.setBody(message.toByteArray()); |
|
|
|
imMessage.write(byteBuf); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|