All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.netty.protocol.dubbo.DubboDecoder Maven / Gradle / Ivy
package com.github.netty.protocol.dubbo;
import com.github.netty.protocol.dubbo.packet.BodyFail;
import com.github.netty.protocol.dubbo.packet.BodyHeartBeat;
import com.github.netty.protocol.dubbo.packet.BodyRequest;
import com.github.netty.protocol.dubbo.packet.BodyResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static com.github.netty.protocol.dubbo.Constant.*;
public class DubboDecoder extends ByteToMessageDecoder {
private State state = State.READ_HEADER;
private DubboPacket packet;
public static boolean isDubboProtocol(ByteBuf buffer) {
return buffer.readableBytes() >= 2
&& buffer.getByte(0) == MAGIC_0
&& buffer.getByte(1) == MAGIC_1;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List out) throws Exception {
boolean hasNext;
do {
switch (this.state) {
case READ_HEADER: {
if (buffer.readableBytes() >= HEADER_LENGTH) {
try {
this.packet = new DubboPacket(readHeader(buffer));
} catch (Exception e) {
exception(ctx, buffer, e);
throw e;
}
this.state = State.READ_BODY;
hasNext = buffer.isReadable();
} else {
hasNext = false;
}
break;
}
case READ_BODY: {
if (buffer.readableBytes() >= this.packet.header.bodyLength) {
ByteBuf body = buffer.readRetainedSlice(this.packet.header.bodyLength);
int markReaderIndex = body.readerIndex();
try {
this.packet.body = readBody(body);
} catch (Exception e) {
exception(ctx, buffer, e);
this.packet.release();
throw e;
}
this.packet.body.markReaderIndex = markReaderIndex;
this.packet.body.bodyBytes = body;
this.state = State.READ_HEADER;
out.add(this.packet);
this.packet = null;
hasNext = buffer.isReadable();
} else {
hasNext = false;
}
break;
}
default: {
hasNext = false;
break;
}
}
} while (hasNext);
}
protected Header readHeader(ByteBuf buffer) {
// request and serialization flag.
byte flag = buffer.getByte(2);
byte status = buffer.getByte(3);
long requestId = buffer.getLong(4);
// 8 - 1-request/0-response
byte type = buffer.getByte(8);
int bodyLength = buffer.getInt(12);
ByteBuf headerBytes = buffer.readRetainedSlice(HEADER_LENGTH);
return new Header(headerBytes, flag, status, requestId, type, bodyLength);
}
protected Body readBody(ByteBuf buffer) throws IOException, ClassNotFoundException {
// request and serialization flag.
byte flag = packet.header.flag;
byte status = packet.header.status;
int bodyLength = packet.header.bodyLength;
boolean flagResponse = (flag & FLAG_REQUEST) == 0;
byte serializationProtoId = (byte) (flag & SERIALIZATION_MASK);
if (flagResponse) {
// decode response.
if (status == OK) {
if ((flag & FLAG_EVENT) != 0) {
return readHeartBeat(buffer, bodyLength, serializationProtoId);
} else {
try (Serialization.ObjectInput in = Serialization.codeOfDeserialize(serializationProtoId, buffer, bodyLength)) {
byte responseWith = buffer.readByte();
BodyResponse packetResponse;
switch (responseWith) {
case RESPONSE_NULL_VALUE:
packetResponse = new BodyResponse(null, null, null);
break;
case RESPONSE_VALUE:
packetResponse = new BodyResponse(in.readObject(), null, null);
break;
case RESPONSE_WITH_EXCEPTION:
packetResponse = new BodyResponse(null, in.readThrowable(), null);
break;
case RESPONSE_NULL_VALUE_WITH_ATTACHMENTS:
packetResponse = new BodyResponse(null, null, in.readAttachments());
break;
case RESPONSE_VALUE_WITH_ATTACHMENTS:
packetResponse = new BodyResponse(in.readObject(), null, in.readAttachments());
break;
case RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS:
packetResponse = new BodyResponse(null, in.readThrowable(), in.readAttachments());
break;
default:
throw new IOException("Unknown result flag, expect '0' '1' '2' '3' '4' '5', but received: " + responseWith);
}
return packetResponse;
}
}
} else {
try (Serialization.ObjectInput in = Serialization.codeOfDeserialize(serializationProtoId, buffer, bodyLength)) {
return new BodyFail(in.readUTF());
}
}
} else {
// decode request.
if ((flag & FLAG_EVENT) != 0) {
return readHeartBeat(buffer, bodyLength, serializationProtoId);
} else {
try (Serialization.ObjectInput in = Serialization.codeOfDeserialize(serializationProtoId, buffer, bodyLength)) {
String dubboVersion = in.readUTF();
String path = in.readUTF();
String version = in.readUTF();
String methodName = in.readUTF();
String parameterTypesDesc = in.readUTF();
int countArgs = countArgs(parameterTypesDesc);
Object[] args = new Object[countArgs];
for (int i = 0; i < countArgs; i++) {
args[i] = in.readArg();
}
Map attachments = in.readAttachments();
return new BodyRequest(dubboVersion, path, version, methodName, parameterTypesDesc, attachments, args);
}
}
}
}
protected BodyHeartBeat readHeartBeat(ByteBuf buffer, int bodyLength, byte serializationProtoId) throws IOException, ClassNotFoundException {
Object data;
byte[] payload = Serialization.getPayload(buffer, bodyLength);
if (Serialization.isHeartBeat(payload, serializationProtoId)) {
data = null;
} else {
try (Serialization.ObjectInput input = Serialization.codeOfDeserialize(serializationProtoId, new ByteArrayInputStream(payload))) {
data = input.readEvent();
}
}
return new BodyHeartBeat(data);
}
protected void exception(ChannelHandlerContext ctx, ByteBuf buffer, E cause) throws Exception {
buffer.release();
ctx.close();
}
protected enum State {
READ_HEADER, READ_BODY
}
}