下面列出了怎么用 io.netty.handler.codec.DecoderException 的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void testFailureDecodeBadChallenge() throws Exception {
// Create a well-formed request
EmbeddedChannel channel = createChannel();
Vote vote = new Vote("Test", "test", "test", "0");
JSONObject object = new JSONObject();
JsonObject payload = vote.serialize();
// We provide the wrong challenge.
payload.addProperty("challenge", "not a challenge for me");
object.put("payload", payload.toString());
String payloadEncoded = GsonInst.gson.toJson(payload);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(TestVotifierPlugin.getI().getTokens().get("default"));
object.put("signature",
Base64.getEncoder().encode(mac.doFinal(payloadEncoded.getBytes(StandardCharsets.UTF_8))));
assertThrows(DecoderException.class, () -> channel.writeInbound(object.toString()));
channel.close();
}
@Test
public void testFailSlowTooLongFrameRecovery() throws Exception {
EmbeddedChannel ch = new EmbeddedChannel(
new DelimiterBasedFrameDecoder(1, true, false, Delimiters.nulDelimiter()));
for (int i = 0; i < 2; i ++) {
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 1, 2 }));
try {
assertTrue(ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0 })));
fail(DecoderException.class.getSimpleName() + " must be raised.");
} catch (TooLongFrameException e) {
// Expected
}
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 'A', 0 }));
ByteBuf buf = releaseLater((ByteBuf) ch.readInbound());
assertEquals("A", buf.toString(CharsetUtil.ISO_8859_1));
}
}
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws DataFormatException {
if (in.readableBytes() != 0) {
int packetLength = PacketBuffer.readVarIntFromBuffer(in);
if (packetLength == 0) {
out.add(in.readBytes(in.readableBytes()));
} else {
if (packetLength < this.threshold) {
throw new DecoderException("Badly compressed packet - size of " + packetLength + " is below server threshold of " + this.threshold);
}
if (packetLength > 2097152) {
throw new DecoderException("Badly compressed packet - size of " + packetLength + " is larger than protocol maximum of " + 2097152);
}
byte[] compressedData = new byte[in.readableBytes()];
in.readBytes(compressedData);
this.inflater.setInput(compressedData);
byte[] decompressedData = new byte[packetLength];
this.inflater.inflate(decompressedData);
out.add(Unpooled.wrappedBuffer(decompressedData));
this.inflater.reset();
}
}
}
public static String readString(ByteBuf byteBuf, int maxLength) {
int length = PacketBuffer.readVarIntFromBuffer(byteBuf);
if (length > maxLength * 4) {
throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + length + " > " + maxLength * 4 + ")");
} else if (length < 0) {
throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!");
} else {
String var2 = byteBuf.toString(byteBuf.readerIndex(), length, org.apache.commons.codec.Charsets.UTF_8);
byteBuf.readerIndex(byteBuf.readerIndex() + length);
if (var2.length() > maxLength) {
throw new DecoderException("The received string length is longer than maximum allowed (" + length + " > " + maxLength + ")");
} else {
return var2;
}
}
}
@Override
public final void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if(cause instanceof DecoderException && cause != null) {
cause = cause.getCause();
}
errorHandler.logError(cause, false);
if(cause instanceof NotSslRecordException) {
log.warn("Someone ({}) speaks transport plaintext instead of ssl, will close the channel", ctx.channel().remoteAddress());
ctx.channel().close();
return;
} else if (cause instanceof SSLException) {
log.error("SSL Problem "+cause.getMessage(),cause);
ctx.channel().close();
return;
} else if (cause instanceof SSLHandshakeException) {
log.error("Problem during handshake "+cause.getMessage());
ctx.channel().close();
return;
}
super.exceptionCaught(ctx, cause);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
Channel ch = ctx.channel();
if (cause instanceof Signal) {
logger.error("I/O signal was caught: {}, force to close channel: {}.", ((Signal) cause).name(), ch);
ch.close();
} else if (cause instanceof IOException) {
logger.error("An I/O exception was caught: {}, force to close channel: {}.", StackTraceUtil.stackTrace(cause), ch);
ch.close();
} else if (cause instanceof DecoderException) {
logger.error("Decoder exception was caught: {}, force to close channel: {}.", StackTraceUtil.stackTrace(cause), ch);
ch.close();
} else {
logger.error("Unexpected exception was caught: {}, channel: {}.", StackTraceUtil.stackTrace(cause), ch);
}
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
// uuid
byte[] uuidBytes = new byte[36];
in.readBytes(uuidBytes);
UUID id = UUID.fromString(new String(uuidBytes));
// op
byte[] opBytes = new byte[4];
in.readBytes(opBytes);
Message.Op op = Message.Op.fromBytes(opBytes);
// payloadSize
byte[] payloadSizeBytes = new byte[4];
in.readBytes(payloadSizeBytes);
int payloadSize = Ints.fromByteArray(payloadSizeBytes);
if (in.readableBytes() < payloadSize) {
ctx.fireExceptionCaught(new DecoderException("Not enough bytes available to decode payload"));
}
out.add(in.readRetainedSlice(payloadSize));
out.add(new Message(id, op));
}
@Test
public void testFailFastTooLongFrameRecovery() throws Exception {
EmbeddedChannel ch = new EmbeddedChannel(
new DelimiterBasedFrameDecoder(1, Delimiters.nulDelimiter()));
for (int i = 0; i < 2; i ++) {
try {
assertTrue(ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 1, 2 })));
fail(DecoderException.class.getSimpleName() + " must be raised.");
} catch (TooLongFrameException e) {
// Expected
}
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0, 'A', 0 }));
ByteBuf buf = releaseLater((ByteBuf) ch.readInbound());
assertEquals("A", buf.toString(CharsetUtil.ISO_8859_1));
}
}
@Override
public String decodeAddress(Socks5AddressType addrType, ByteBuf in) throws Exception {
if (addrType == Socks5AddressType.IPv4) {
return NetUtil.intToIpAddress(in.readInt());
}
if (addrType == Socks5AddressType.DOMAIN) {
final int length = in.readUnsignedByte();
final String domain = in.toString(in.readerIndex(), length, CharsetUtil.US_ASCII);
in.skipBytes(length);
return domain;
}
if (addrType == Socks5AddressType.IPv6) {
if (in.hasArray()) {
final int readerIdx = in.readerIndex();
in.readerIndex(readerIdx + IPv6_LEN);
return NetUtil.bytesToIpAddress(in.array(), in.arrayOffset() + readerIdx, IPv6_LEN);
} else {
byte[] tmp = new byte[IPv6_LEN];
in.readBytes(tmp);
return NetUtil.bytesToIpAddress(tmp);
}
} else {
throw new DecoderException("unsupported address type: " + (addrType.byteValue() & 0xFF));
}
}
@Test
public void testFailureDecodeBadVoteField() throws Exception {
// Create a well-formed request
EmbeddedChannel channel = createChannel();
Vote vote = new Vote("Test", "test", "test", "0");
JSONObject object = new JSONObject();
JsonObject payload = vote.serialize();
String payloadEncoded = GsonInst.gson.toJson(payload);
// We "forget" the challenge.
object.put("payload", payloadEncoded);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(TestVotifierPlugin.getI().getTokens().get("default"));
object.put("signature",
Base64.getEncoder().encodeToString(mac.doFinal(payloadEncoded.getBytes(StandardCharsets.UTF_8))));
assertThrows(DecoderException.class, () -> channel.writeInbound(object.toString()));
channel.close();
}
@Test
public void testFailSlowTooLongFrameRecovery() throws Exception {
EmbeddedChannel ch = new EmbeddedChannel(
new DelimiterBasedFrameDecoder(1, true, false, Delimiters.nulDelimiter()));
for (int i = 0; i < 2; i ++) {
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 1, 2 }));
try {
assertTrue(ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0 })));
fail(DecoderException.class.getSimpleName() + " must be raised.");
} catch (TooLongFrameException e) {
// Expected
}
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 'A', 0 }));
ByteBuf buf = ch.readInbound();
assertEquals("A", buf.toString(CharsetUtil.ISO_8859_1));
buf.release();
}
}
@Test
public void testFailSlowTooLongFrameRecovery() throws Exception {
EmbeddedChannel ch = new EmbeddedChannel(
new LengthFieldBasedFrameDecoder(5, 0, 4, 0, 4, false));
for (int i = 0; i < 2; i ++) {
assertFalse(ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0, 0, 0, 2 })));
try {
assertTrue(ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0, 0 })));
fail(DecoderException.class.getSimpleName() + " must be raised.");
} catch (TooLongFrameException e) {
// Expected
}
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0, 0, 0, 1, 'A' }));
ByteBuf buf = releaseLater((ByteBuf) ch.readInbound());
assertEquals("A", buf.toString(CharsetUtil.ISO_8859_1));
buf.release();
}
}
@Test
public void testFailFastTooLongFrameRecovery() throws Exception {
EmbeddedChannel ch = new EmbeddedChannel(
new LengthFieldBasedFrameDecoder(5, 0, 4, 0, 4));
for (int i = 0; i < 2; i ++) {
try {
assertTrue(ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0, 0, 0, 2 })));
fail(DecoderException.class.getSimpleName() + " must be raised.");
} catch (TooLongFrameException e) {
// Expected
}
ch.writeInbound(Unpooled.wrappedBuffer(new byte[] { 0, 0, 0, 0, 0, 1, 'A' }));
ByteBuf buf = ch.readInbound();
assertEquals("A", buf.toString(CharsetUtil.ISO_8859_1));
buf.release();
}
}
/**
* Called once data should be decoded from the given {@link ByteBuf}. This method will call
* {@link #decode(ChannelHandlerContext, ByteBuf)} as long as decoding should take place.
*
* @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
* @param in the {@link ByteBuf} from which to read data
*/
private void callDecode(CtxWrapper ctx, ByteBuf in) {
try {
while (in.isReadable() && !ctx.isRemoved()) {
int fireChannelReadCount = ctx.getFireChannelReadCount();
int oldInputLength = in.readableBytes();
decodeRemovalReentryProtection(ctx, in);
if (ctx.isRemoved()) {
break;
}
if (fireChannelReadCount == ctx.getFireChannelReadCount()) {
if (oldInputLength == in.readableBytes()) {
break;
}
} else if (oldInputLength == in.readableBytes()) {
throw new DecoderException(
StringUtil.simpleClassName(getClass()) +
".decode() did not read anything but decoded a message.");
}
}
} catch (DecoderException e) {
throw e;
} catch (Exception cause) {
throw new DecoderException(cause);
}
}
@Override
public void onError(final Throwable t) {
if (t instanceof CloseEventObservedException) {
final CloseEventObservedException ceoe = (CloseEventObservedException) t;
if (ceoe.event() == CHANNEL_CLOSED_INBOUND && t.getCause() instanceof ClosedChannelException) {
LOGGER.trace("Client closed the connection without sending 'Connection: close' header", t);
return;
}
if (t.getCause() instanceof DecoderException) {
LOGGER.warn("Can not decode HTTP message, no more requests will be received on this connection.",
t);
return;
}
}
LOGGER.debug("Unexpected error received while processing connection, {}",
"no more requests will be received on this connection.", t);
}
/**
* In the interest of robustness, a peer that is expecting to receive and parse a start-line SHOULD ignore at
* least one empty line (CRLF) received prior to the request-line.
*
* @see <a href="https://tools.ietf.org/html/rfc7230#section-3.5">RFC7230, Message Parsing Robustness</a>
*/
private boolean skipControlCharacters(final ByteBuf buffer) {
if (cumulationIndex < 0) {
cumulationIndex = buffer.readerIndex();
}
final int readableBytes = buffer.writerIndex() - cumulationIndex;
// Look at one more character than allowed to expect a valid VCHAR:
final int len = min(MAX_ALLOWED_CHARS_TO_SKIP_PLUS_ONE - skippedControls, readableBytes);
final int i = buffer.forEachByte(cumulationIndex, len, SKIP_PREFACING_CRLF);
if (i < 0) {
skippedControls += len;
if (skippedControls > MAX_ALLOWED_CHARS_TO_SKIP) {
throw new DecoderException("Too many prefacing CRLF characters");
}
cumulationIndex += len;
buffer.readerIndex(cumulationIndex);
return false;
} else {
cumulationIndex = i;
buffer.readerIndex(i);
return true;
}
}
@Parameters(name =
"serverAlpnProtocols={0}, clientAlpnProtocols={1}, expectedProtocol={2}, expectedExceptionType={3}")
public static Collection<Object[]> clientExecutors() {
return asList(new Object[][] {
{asList(HTTP_2, HTTP_1_1), asList(HTTP_2, HTTP_1_1), HttpProtocolVersion.HTTP_2_0, null},
{asList(HTTP_2, HTTP_1_1), asList(HTTP_1_1, HTTP_2), HttpProtocolVersion.HTTP_2_0, null},
{asList(HTTP_2, HTTP_1_1), singletonList(HTTP_2), HttpProtocolVersion.HTTP_2_0, null},
{asList(HTTP_2, HTTP_1_1), singletonList(HTTP_1_1), HttpProtocolVersion.HTTP_1_1, null},
{asList(HTTP_1_1, HTTP_2), asList(HTTP_2, HTTP_1_1), HttpProtocolVersion.HTTP_1_1, null},
{asList(HTTP_1_1, HTTP_2), asList(HTTP_1_1, HTTP_2), HttpProtocolVersion.HTTP_1_1, null},
{asList(HTTP_1_1, HTTP_2), singletonList(HTTP_2), HttpProtocolVersion.HTTP_2_0, null},
{asList(HTTP_1_1, HTTP_2), singletonList(HTTP_1_1), HttpProtocolVersion.HTTP_1_1, null},
{singletonList(HTTP_2), asList(HTTP_2, HTTP_1_1), HttpProtocolVersion.HTTP_2_0, null},
{singletonList(HTTP_2), asList(HTTP_1_1, HTTP_2), HttpProtocolVersion.HTTP_2_0, null},
{singletonList(HTTP_2), singletonList(HTTP_2), HttpProtocolVersion.HTTP_2_0, null},
{singletonList(HTTP_2), singletonList(HTTP_1_1), null, DecoderException.class},
{singletonList(HTTP_1_1), asList(HTTP_2, HTTP_1_1), HttpProtocolVersion.HTTP_1_1, null},
{singletonList(HTTP_1_1), asList(HTTP_1_1, HTTP_2), HttpProtocolVersion.HTTP_1_1, null},
{singletonList(HTTP_1_1), singletonList(HTTP_2), null, ClosedChannelException.class},
{singletonList(HTTP_1_1), singletonList(HTTP_1_1), HttpProtocolVersion.HTTP_1_1, null},
});
}
@Override
public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
Channel channel = context.channel();
if(cause instanceof IOException && cause.getMessage().equals("Connection reset by peer")) {
// ignore
} else if(cause instanceof ReadTimeoutException) {
// ignore
} else if(cause instanceof DecoderException) {
// ignore
} else {
cause.printStackTrace();
}
if(channel.isOpen()) {
channel.close();
}
}
public static void readDataTo(ByteBuf from, ArrayMap<NetworkEntityMetadataObject<?>> to) {
do {
int key = from.readUnsignedByte();
if (key == 0xFF) {
break;
}
int type = from.readUnsignedByte();
try {
ReadableNetworkEntityMetadataObject<?> object = registry[type].get();
object.readFromStream(from);
to.put(key, object);
} catch (Exception e) {
throw new DecoderException(MessageFormat.format("Unable to decode datawatcher object (type: {0}, index: {1})", type, key), e);
}
} while (true);
}
@Override
protected void decodePacket(ChannelHandlerContext ctx, int sequenceId, ByteBuf packet, List<Object> out) {
MysqlCharacterSet clientCharset = session.getClientCharset();
byte commandCode = packet.readByte();
Command command = Command.findByCommandCode(commandCode);
if (command == null) {
throw new DecoderException("Unknown command " + commandCode);
}
switch (command) {
case COM_QUERY:
out.add(new ClientQueryPacket(sequenceId, CodecUtils.readFixedLengthString(packet, packet.readableBytes(), clientCharset.getCharset())));
break;
default:
out.add(new ClientCommandPacket(sequenceId, command));
}
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
Connection connection = ctx.channel().attr(AttributeKey.<Connection>valueOf("connection")).get();
SecretKey sharedSecret = connection.getSharedSecret();
if (cipher == null) {
cipher = Cipher.getInstance("AES/CFB8/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, sharedSecret, new IvParameterSpec(sharedSecret.getEncoded()));
}
ByteBuffer outNioBuf = ByteBuffer.allocate(in.readableBytes());
try {
cipher.update(in.nioBuffer(), outNioBuf);
} catch (ShortBufferException e) {
throw new DecoderException("encryption output buffer too small", e);
}
outNioBuf.flip();
out.add(Unpooled.wrappedBuffer(outNioBuf));
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
try {
Packet packet = (Packet) msg;
Connection connection = ctx.channel().attr(AttributeKey.<Connection>valueOf("connection")).get();
if (packet.getType().getDirection() == PacketDirection.INBOUND) {
throw new DecoderException("Outbound packet has invalid direction: " + packet.getType());
}
if (CleanstoneServer.publishEvent(
new OutboundPacketEvent<>(packet, connection, networking)).isCancelled()) {
return;
}
log.trace("Sending " + packet.getType() + " (" + networking.getProtocol().translateOutboundPacketID(packet.getType(), connection) + ") packet to " + connection.getAddress().getHostAddress());
ctx.write(packet, promise);
} catch (Exception e) {
log.error("Error occurred while handling outbound packet", e);
}
}
public static String readString(ByteBuf buf, int max) {
int length = readVarInt(buf);
if (length > max * 4) {
throw new DecoderException("The received encoded string buffer length is longer than maximum allowed (" + length + " > " + max * 4 + ")");
}
if (length < 0) {
throw new DecoderException("The received encoded string buffer length is less than zero! Weird string!");
}
String s = buf.toString(buf.readerIndex(), length, StandardCharsets.UTF_8);
if (s.length() > max) {
throw new DecoderException("The received string length is longer than maximum allowed (" + s.length() + " > " + max + ")");
}
buf.skipBytes(length);
return s;
}
@Test
public void testErrorInvalidPayload() {
thrown.expect(DecoderException.class);
thrown.expectMessage("Not enough bytes available to decode payload");
UUID id = UUID.fromString("3f127172-0245-4018-b52d-a8967bd94e7d");
Message.Op op = Message.Op.Response;
int payloadSize = 4;
Integer payload = new Integer(1);
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(id.toString().getBytes());
buf.writeBytes(Ints.toByteArray(op.ordinal()));
buf.writeBytes(Ints.toByteArray(payloadSize));
channel.writeInbound(buf);
}
private Function convertFunction ( final int functions )
{
switch ( functions )
{
case 0x03 | 4:
return Function.STARTDT_ACT;
case 0x03 | 8:
return Function.STARTDT_CONFIRM;
case 0x03 | 16:
return Function.STOPDT_ACT;
case 0x03 | 32:
return Function.STOPDT_CONFIRM;
case 0x03 | 64:
return Function.TESTFR_ACT;
case 0x03 | 128:
return Function.TESTFR_CONFIRM;
default:
throw new DecoderException ( String.format ( "Invalid function codes for U-format (%02x)", functions ) );
}
}
void upgradeToSSLConnection(Handler<AsyncResult<Void>> completionHandler) {
ChannelPipeline pipeline = socket.channelHandlerContext().pipeline();
Promise<Void> upgradePromise = Promise.promise();
upgradePromise.future().onComplete(ar->{
if (ar.succeeded()) {
completionHandler.handle(Future.succeededFuture());
} else {
Throwable cause = ar.cause();
if (cause instanceof DecoderException) {
DecoderException err = (DecoderException) cause;
cause = err.getCause();
}
completionHandler.handle(Future.failedFuture(cause));
}
});
pipeline.addBefore("handler", "initiate-ssl-handler", new InitiateSslHandler(this, upgradePromise));
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> packets) throws Exception {
if (!buf.isReadable()) {
return;
}
buf.markReaderIndex();
ReadableMiddlePacket transformer = registry.getTransformer(Protocol.GAME, buf.readUnsignedByte(), false);
if (transformer != null) {
transformer.read(buf);
if (buf.isReadable()) {
throw new DecoderException("Did not read all data from packet " + transformer.getClass().getName() + ", bytes left: " + buf.readableBytes());
}
packets.addAll(transformer.toNative());
} else {
buf.resetReaderIndex();
packets.add(new PacketWrapper(null, buf.copy()));
}
}
@Override
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable throwable)
throws Exception {
final Throwable cause =
throwable instanceof DecoderException && throwable.getCause() != null
? throwable.getCause()
: throwable;
if (cause instanceof FramingException
|| cause instanceof RLPException
|| cause instanceof IllegalArgumentException) {
LOG.debug("Invalid incoming message", throwable);
if (connectFuture.isDone() && !connectFuture.isCompletedExceptionally()) {
connectFuture.get().disconnect(DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL);
return;
}
} else if (cause instanceof IOException) {
// IO failures are routine when communicating with random peers across the network.
LOG.debug("IO error while processing incoming message", throwable);
} else {
LOG.error("Exception while processing incoming message", throwable);
}
if (connectFuture.isDone() && !connectFuture.isCompletedExceptionally()) {
connectFuture
.get()
.terminateConnection(DisconnectMessage.DisconnectReason.TCP_SUBSYSTEM_ERROR, true);
} else {
connectFuture.completeExceptionally(throwable);
ctx.close();
}
}
private synchronized void handleException(Throwable t) {
if (t instanceof DecoderException) {
DecoderException err = (DecoderException) t;
t = err.getCause();
}
handleClose(t);
}
@Test
public void exceptionCaught_shouldDisconnectForBreachOfProtocolWhenRlpExceptionThrown()
throws Exception {
connectFuture.complete(peerConnection);
deFramer.exceptionCaught(ctx, new DecoderException(new RLPException("Test")));
verify(peerConnection).disconnect(DisconnectReason.BREACH_OF_PROTOCOL);
}