Java tutorial
/* * Copyright (c) 2014. Lorem ipsum dolor sit amet, consectetur adipiscing elit. * http://www.apache.org/licenses/LICENSE-2.0 */ package net.NettyEngine4; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.CorruptedFrameException; import io.netty.handler.codec.TooLongFrameException; import java.nio.ByteOrder; import java.util.List; /** * ChannelInboundHandler * ChannelHandler? * final DefaultChannelHandlerContext next = findContextInbound(); * EventExecutor executor = next.executor(); * ? executor?? * fireChannelRead(final Object msg) I/O???? ServerHandlerchannelRead?? * * BIG_ENDIAN?? */ public class ServerDecoder extends ByteToMessageDecoder { private final ByteOrder byteOrder; // BIG_ENDIAN private final int maxFrameLength; private final int lengthFieldOffset; private final int lengthFieldLength; private final int lengthFieldEndOffset; private final int lengthAdjustment; private final int initialBytesToStrip; private final boolean failFast; private boolean discardingTooLongFrame; private long tooLongFrameLength; private long bytesToDiscard; /** * * @param maxFrameLength * @param lengthFieldOffset * @param lengthFieldLength * @param lengthAdjustment * @param initialBytesToStrip */ public ServerDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip) { this(maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, true); } /** * * @param maxFrameLength * @param lengthFieldOffset * @param lengthFieldLength * @param lengthAdjustment * @param initialBytesToStrip * @param failFast * If <tt>true</tt>, a {@link io.netty.handler.codec.TooLongFrameException} is thrown as * soon as the decoder notices the length of the frame will exceed * <tt>maxFrameLength</tt> regardless of whether the entire frame * has been read. If <tt>false</tt>, a {@link io.netty.handler.codec.TooLongFrameException} * is thrown after the entire frame that exceeds <tt>maxFrameLength</tt> * has been read. */ public ServerDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) { this(ByteOrder.BIG_ENDIAN, maxFrameLength, lengthFieldOffset, lengthFieldLength, lengthAdjustment, initialBytesToStrip, failFast); } /** * * @param byteOrder ? * @param maxFrameLength ? * @param lengthFieldOffset ??? * @param lengthFieldLength ? * @param lengthAdjustment * @param initialBytesToStrip ? * @param failFast */ public ServerDecoder(ByteOrder byteOrder, int maxFrameLength, int lengthFieldOffset, int lengthFieldLength, int lengthAdjustment, int initialBytesToStrip, boolean failFast) { this.byteOrder = byteOrder; this.maxFrameLength = maxFrameLength; this.lengthFieldOffset = lengthFieldOffset; this.lengthFieldLength = lengthFieldLength; this.lengthAdjustment = lengthAdjustment; lengthFieldEndOffset = lengthFieldOffset + lengthFieldLength; this.initialBytesToStrip = initialBytesToStrip; this.failFast = failFast; } /** * decode message will be added the MessageList<Object> out queue! * @param ctx * @param in read data * @param out ?? * @throws Exception * ?channel OutputMessageBuf? * I/O ? ???? */ @Override protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { //decode message to list if (discardingTooLongFrame) { long bytesToDiscard = this.bytesToDiscard; int localBytesToDiscard = (int) Math.min(bytesToDiscard, in.readableBytes()); in.skipBytes(localBytesToDiscard); bytesToDiscard -= localBytesToDiscard; this.bytesToDiscard = bytesToDiscard; failIfNecessary(ctx, false); return; } if (in.readableBytes() < lengthFieldEndOffset) { return; } int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset; /**?? 124,???short 2*/ long frameLength = (in.order(byteOrder)).getUnsignedShort(actualLengthFieldOffset); if (frameLength < 0) { in.skipBytes(lengthFieldEndOffset); throw new CorruptedFrameException("negative pre-adjustment length field: " + frameLength); } frameLength += lengthAdjustment + lengthFieldEndOffset; if (frameLength < lengthFieldEndOffset) { in.skipBytes(lengthFieldEndOffset); throw new CorruptedFrameException("Adjusted frame length (" + frameLength + ") is less " + "than lengthFieldEndOffset: " + lengthFieldEndOffset); } if (frameLength > maxFrameLength) { // Enter the discard mode and discard everything received so far. discardingTooLongFrame = true; tooLongFrameLength = frameLength; bytesToDiscard = frameLength - in.readableBytes(); in.skipBytes(in.readableBytes()); failIfNecessary(ctx, true); return; } // never overflows because it's less than maxFrameLength int frameLengthInt = (int) frameLength; if (in.readableBytes() < frameLengthInt) { return; } if (initialBytesToStrip > frameLengthInt) { in.skipBytes(frameLengthInt); throw new CorruptedFrameException("Adjusted frame length (" + frameLength + ") is less " + "than initialBytesToStrip: " + initialBytesToStrip); } //skip head in.skipBytes(initialBytesToStrip); // extract frame int readerIndex = in.readerIndex(); int actualFrameLength = frameLengthInt - initialBytesToStrip; //? ByteBuf frame = ctx.alloc().heapBuffer(actualFrameLength); //heap buffer frame.writeBytes(in, readerIndex, actualFrameLength); in.readerIndex(readerIndex + actualFrameLength); //set reader Index //decode message and add to list this is byteBuffer if (frame != null) { out.add(frame); } } /** * * @param ctx * @param firstDetectionOfTooLongFrame */ private void failIfNecessary(ChannelHandlerContext ctx, boolean firstDetectionOfTooLongFrame) { if (bytesToDiscard == 0) { // Reset to the initial state and tell the handlers that // the frame was too large. long tooLongFrameLength = this.tooLongFrameLength; this.tooLongFrameLength = 0; discardingTooLongFrame = false; if (!failFast || failFast && firstDetectionOfTooLongFrame) { fail(tooLongFrameLength); } } else { // Keep discarding and notify handlers if necessary. if (failFast && firstDetectionOfTooLongFrame) { fail(tooLongFrameLength); } } } //logger fail private void fail(long frameLength) { if (frameLength > 0) { throw new TooLongFrameException( "Adjusted frame length exceeds " + maxFrameLength + ": " + frameLength + " - discarded"); } else { throw new TooLongFrameException("Adjusted frame length exceeds " + maxFrameLength + " - discarding"); } } }