ProtocolCodecFilter: An IoFilter which translates binary or protocol specific data into message objects and vice versa 。
在解码过程中遇到异常,会把异常的这段字节序保存下来。
@Override
public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception {
LOGGER.debug("Processing a MESSAGE_RECEIVED for session {}", session.getId());
if (!(message instanceof IoBuffer)) {
nextFilter.messageReceived(session, message);
return;
}
IoBuffer in = (IoBuffer) message;
ProtocolDecoder decoder = factory.getDecoder(session);
ProtocolDecoderOutput decoderOut = getDecoderOut(session, nextFilter);
// Loop until we don't have anymore byte in the buffer,
// or until the decoder throws an unrecoverable exception or
// can't decoder a message, because there are not enough
// data in the buffer
while (in.hasRemaining()) {
//在解码前,把当前位置记录下来
int oldPos = in.position();
try {
synchronized (decoderOut) {
// Call the decoder with the read bytes
decoder.decode(session, in, decoderOut);
}
// Finish decoding if no exception was thrown.
decoderOut.flush(nextFilter, session);
} catch (Throwable t) {
ProtocolDecoderException pde;
if (t instanceof ProtocolDecoderException) {
pde = (ProtocolDecoderException) t;
} else {
pde = new ProtocolDecoderException(t);
}
if (pde.getHexdump() == null) {
// Generate a message hex dump
//当异常出现时,把解码前到当前位置的网络字节序保存下来。生成16进制字符串。
int curPos = in.position();
in.position(oldPos);
pde.setHexdump(in.getHexDump());
in.position(curPos);
}
// Fire the exceptionCaught event.
decoderOut.flush(nextFilter, session);
nextFilter.exceptionCaught(session, pde);
// Retry only if the type of the caught exception is
// recoverable and the buffer position has changed.
// We check buffer position additionally to prevent an
// infinite loop.
if (!(t instanceof RecoverableProtocolDecoderException) || (in.position() == oldPos)) {
break;
}
}
}
}
IoBufferHexDumper: Provides utility methods to dump an IoBuffer into a hex formatted string.
class IoBufferHexDumper {
/**
* The high digits lookup table.
*/
private static final byte[] highDigits;
/**
* The low digits lookup table.
*/
private static final byte[] lowDigits;
/**
* Initialize lookup tables.
*/
static {
final byte[] digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
int i;
byte[] high = new byte[256];
byte[] low = new byte[256];
for (i = 0; i < 256; i++) {
high[i] = digits[i >>> 4];
low[i] = digits[i & 0x0F];
}
highDigits = high;
lowDigits = low;
}
/**
* Dumps an {@link IoBuffer} to a hex formatted string.
*
* @param in the buffer to dump
* @param lengthLimit the limit at which hex dumping will stop
* @return a hex formatted string representation of the <i>in</i> {@link Iobuffer}.
*/
public static String getHexdump(IoBuffer in, int lengthLimit) {
if (lengthLimit == 0) {
throw new IllegalArgumentException("lengthLimit: " + lengthLimit + " (expected: 1+)");
}
boolean truncate = in.remaining() > lengthLimit;
int size;
if (truncate) {
size = lengthLimit;
} else {
size = in.remaining();
}
if (size == 0) {
return "empty";
}
StringBuilder out = new StringBuilder(size * 3 + 3);
int mark = in.position();
// fill the first
int byteValue = in.get() & 0xFF;
out.append((char) highDigits[byteValue]);
out.append((char) lowDigits[byteValue]);
size--;
//把每一个字节变成16进制。并且用空格隔开,这样容易阅读。
// and the others, too
for (; size > 0; size--) {
out.append(' ');
byteValue = in.get() & 0xFF;
out.append((char) highDigits[byteValue]);
out.append((char) lowDigits[byteValue]);
}
in.position(mark);
if (truncate) {
out.append("...");
}
return out.toString();
}
}
在netty中,ByteBufUtil中存在
public static String hexDump(ByteBuf buffer, int fromIndex, int length)
public static String hexDump(byte[] array, int fromIndex, int length)
可以把ByteBuf和Array转换成16进制。
在JsonObjectDecoder 和SniHandler 等在异常情况下把网络字节序dump下来。