use of org.apache.dubbo.remoting.exchange.Response in project dubbo by alibaba.
the class ExchangeCodec method encodeResponse.
protected void encodeResponse(Channel channel, ChannelBuffer buffer, Response res) throws IOException {
int savedWriteIndex = buffer.writerIndex();
try {
Serialization serialization = getSerialization(channel, res);
// header.
byte[] header = new byte[HEADER_LENGTH];
// set magic number.
Bytes.short2bytes(MAGIC, header);
// set request and serialization flag.
header[2] = serialization.getContentTypeId();
if (res.isHeartbeat()) {
header[2] |= FLAG_EVENT;
}
// set response status.
byte status = res.getStatus();
header[3] = status;
// set request id.
Bytes.long2bytes(res.getId(), header, 4);
buffer.writerIndex(savedWriteIndex + HEADER_LENGTH);
ChannelBufferOutputStream bos = new ChannelBufferOutputStream(buffer);
// encode response data or error message.
if (status == Response.OK) {
if (res.isHeartbeat()) {
// heartbeat response data is always null
bos.write(CodecSupport.getNullBytesOf(serialization));
} else {
ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
if (res.isEvent()) {
encodeEventData(channel, out, res.getResult());
} else {
encodeResponseData(channel, out, res.getResult(), res.getVersion());
}
out.flushBuffer();
if (out instanceof Cleanable) {
((Cleanable) out).cleanup();
}
}
} else {
ObjectOutput out = serialization.serialize(channel.getUrl(), bos);
out.writeUTF(res.getErrorMessage());
out.flushBuffer();
if (out instanceof Cleanable) {
((Cleanable) out).cleanup();
}
}
bos.flush();
bos.close();
int len = bos.writtenBytes();
checkPayload(channel, len);
Bytes.int2bytes(len, header, 12);
// write
buffer.writerIndex(savedWriteIndex);
// write header.
buffer.writeBytes(header);
buffer.writerIndex(savedWriteIndex + HEADER_LENGTH + len);
} catch (Throwable t) {
// clear buffer
buffer.writerIndex(savedWriteIndex);
// send error message to Consumer, otherwise, Consumer will wait till timeout.
if (!res.isEvent() && res.getStatus() != Response.BAD_RESPONSE) {
Response r = new Response(res.getId(), res.getVersion());
r.setStatus(Response.BAD_RESPONSE);
if (t instanceof ExceedPayloadLimitException) {
logger.warn(t.getMessage(), t);
try {
r.setErrorMessage(t.getMessage());
channel.send(r);
return;
} catch (RemotingException e) {
logger.warn("Failed to send bad_response info back: " + t.getMessage() + ", cause: " + e.getMessage(), e);
}
} else {
// FIXME log error message in Codec and handle in caught() of IoHanndler?
logger.warn("Fail to encode response: " + res + ", send bad_response info instead, cause: " + t.getMessage(), t);
try {
r.setErrorMessage("Failed to send response: " + res + ", cause: " + StringUtils.toString(t));
channel.send(r);
return;
} catch (RemotingException e) {
logger.warn("Failed to send bad_response info back: " + res + ", cause: " + e.getMessage(), e);
}
}
}
// Rethrow exception
if (t instanceof IOException) {
throw (IOException) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else if (t instanceof Error) {
throw (Error) t;
} else {
throw new RuntimeException(t.getMessage(), t);
}
}
}
use of org.apache.dubbo.remoting.exchange.Response in project dubbo by alibaba.
the class ExchangeCodec method finishRespWhenOverPayload.
private Object finishRespWhenOverPayload(Channel channel, long size, byte[] header) {
int payload = getPayload(channel);
boolean overPayload = isOverPayload(payload, size);
if (overPayload) {
long reqId = Bytes.bytes2long(header, 4);
byte flag = header[2];
if ((flag & FLAG_REQUEST) == 0) {
Response res = new Response(reqId);
if ((flag & FLAG_EVENT) != 0) {
res.setEvent(true);
}
res.setStatus(Response.CLIENT_ERROR);
String errorMsg = "Data length too large: " + size + ", max payload: " + payload + ", channel: " + channel;
logger.error(errorMsg);
res.setErrorMessage(errorMsg);
return res;
}
}
return null;
}
use of org.apache.dubbo.remoting.exchange.Response in project dubbo by alibaba.
the class NettyClientHandler method write.
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
super.write(ctx, msg, promise);
final NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
final boolean isRequest = msg instanceof Request;
// We add listeners to make sure our out bound event is correct.
// If our out bound event has an error (in most cases the encoder fails),
// we need to have the request return directly instead of blocking the invoke process.
promise.addListener(future -> {
if (future.isSuccess()) {
// if our future is success, mark the future to sent.
handler.sent(channel, msg);
return;
}
Throwable t = future.cause();
if (t != null && isRequest) {
Request request = (Request) msg;
Response response = buildErrorResponse(request, t);
handler.received(channel, response);
}
});
}
use of org.apache.dubbo.remoting.exchange.Response in project dubbo by alibaba.
the class NettyClientHandler method buildErrorResponse.
/**
* build a bad request's response
*
* @param request the request
* @param t the throwable. In most cases, serialization fails.
* @return the response
*/
private static Response buildErrorResponse(Request request, Throwable t) {
Response response = new Response(request.getId(), request.getVersion());
response.setStatus(Response.BAD_REQUEST);
response.setErrorMessage(StringUtils.toString(t));
return response;
}
use of org.apache.dubbo.remoting.exchange.Response in project dubbo by alibaba.
the class ThriftCodecTest method testDecodeExceptionResponse.
@Test
public void testDecodeExceptionResponse() throws Exception {
int port = NetUtils.getAvailablePort();
URL url = URL.valueOf(ThriftProtocol.NAME + "://127.0.0.1:" + port + "/" + Demo.class.getName());
Channel channel = new MockedChannel(url);
RandomAccessByteArrayOutputStream bos = new RandomAccessByteArrayOutputStream(128);
Request request = createRequest();
DefaultFuture future = DefaultFuture.newFuture(channel, request, 10, null);
TMessage message = new TMessage("echoString", TMessageType.EXCEPTION, ThriftCodec.getSeqId());
TTransport transport = new TIOStreamTransport(bos);
TBinaryProtocol protocol = new TBinaryProtocol(transport);
TApplicationException exception = new TApplicationException();
int messageLength, headerLength;
// prepare
protocol.writeI16(ThriftCodec.MAGIC);
protocol.writeI32(Integer.MAX_VALUE);
protocol.writeI16(Short.MAX_VALUE);
protocol.writeByte(ThriftCodec.VERSION);
protocol.writeString(Demo.class.getName());
// path
protocol.writeString(Demo.class.getName());
protocol.writeI64(request.getId());
protocol.getTransport().flush();
headerLength = bos.size();
protocol.writeMessageBegin(message);
exception.write(protocol);
protocol.writeMessageEnd();
protocol.getTransport().flush();
int oldIndex = messageLength = bos.size();
try {
bos.setWriteIndex(ThriftCodec.MESSAGE_LENGTH_INDEX);
protocol.writeI32(messageLength);
bos.setWriteIndex(ThriftCodec.MESSAGE_HEADER_LENGTH_INDEX);
protocol.writeI16((short) (0xffff & headerLength));
} finally {
bos.setWriteIndex(oldIndex);
}
// prepare
ChannelBuffer bis = ChannelBuffers.wrappedBuffer(encodeFrame(bos.toByteArray()));
Object obj = codec.decode((Channel) null, bis);
Assertions.assertNotNull(obj);
Assertions.assertTrue(obj instanceof Response);
Response response = (Response) obj;
Assertions.assertTrue(response.getResult() instanceof AppResponse);
AppResponse result = (AppResponse) response.getResult();
Assertions.assertTrue(result.hasException());
Assertions.assertTrue(result.getException() instanceof RpcException);
}
Aggregations