@Override public void messageReceived( ChannelHandlerContext ctx, MessageEvent e) throws Exception { Object m = e.getMessage(); if (!(m instanceof ChannelBuffer)) { ctx.sendUpstream(e); return; } ChannelBuffer input = (ChannelBuffer) m; if (!input.readable()) { return; } if (cumulation == null) { try { // the cumulation buffer is not created yet so just pass the input to callDecode(...) method callDecode(ctx, e.getChannel(), input, e.getRemoteAddress()); } finally { updateCumulation(ctx, input); } } else { input = appendToCumulation(input); try { callDecode(ctx, e.getChannel(), input, e.getRemoteAddress()); } finally { updateCumulation(ctx, input); } } }
@Override public void beforeAdd(ChannelHandlerContext ctx) throws Exception { super.beforeAdd(ctx); this.ctx = ctx; }
/** * Calls {@link #handshake()} once the {@link Channel} is connected */ @Override public void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { if (issueHandshake) { // issue and handshake and add a listener to it which will fire an exception event if // an exception was thrown while doing the handshake handshake().addListener(new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { // Send the event upstream after the handshake was completed without an error. // // See https://github.com/netty/netty/issues/358 ctx.sendUpstream(e); } } }); } else { super.channelConnected(ctx, e); } }
/** * Gets called on {@link #channelDisconnected(ChannelHandlerContext, ChannelStateEvent)} and * {@link #channelClosed(ChannelHandlerContext, ChannelStateEvent)} */ protected void cleanup(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { try { ChannelBuffer cumulation = this.cumulation; if (cumulation == null) { return; } this.cumulation = null; if (cumulation.readable()) { // Make sure all frames are read before notifying a closed channel. callDecode(ctx, ctx.getChannel(), cumulation, null); } // Call decodeLast() finally. Please note that decodeLast() is // called even if there's nothing more to read from the buffer to // notify a user that the connection was closed explicitly. Object partialFrame = decodeLast(ctx, ctx.getChannel(), cumulation); if (partialFrame != null) { unfoldAndFireMessageReceived(ctx, null, partialFrame); } } finally { ctx.sendUpstream(e); } }
@Override public void handleUpstream(final ChannelHandlerContext ctx, final ChannelEvent ce) throws Exception { if (!handshakeDone || !rtmpe || !(ce instanceof MessageEvent)) { super.handleUpstream(ctx, ce); return; } final MessageEvent me = (MessageEvent) ce; if(me.getMessage() instanceof RtmpPublisher.Event) { super.handleUpstream(ctx, ce); return; } final ChannelBuffer in = (ChannelBuffer) ((MessageEvent) ce).getMessage(); handshake.cipherUpdateIn(in); Channels.fireMessageReceived(ctx, in); }
@Override protected ChannelBuffer newCumulationBuffer(ChannelHandlerContext ctx, int minimumCapacity) { ChannelBufferFactory factory = ctx.getChannel().getConfig().getBufferFactory(); if (allocateFullBuffer) { return factory.getBuffer(frameLength); } return super.newCumulationBuffer(ctx, minimumCapacity); } }
super.channelClosed(ctx, e);
@Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { logger.error("decode protocol failed!", e.getCause()); ctx.getChannel().close(); super.exceptionCaught(ctx, e); }
@Override public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { // Make sure the handshake future is notified when a connection has // been closed during handshake. synchronized (handshakeLock) { if (handshaking) { cancelHandshakeTimeout(); handshakeFuture.setFailure(new ClosedChannelException()); } } try { super.channelDisconnected(ctx, e); } finally { unwrapNonAppData(ctx, e.getChannel(), false); closeEngine(); } }
/** * Replace this {@link FrameDecoder} in the {@link ChannelPipeline} with the given {@link ChannelHandler}. All * remaining bytes in the {@link ChannelBuffer} will get send to the new {@link ChannelHandler} that was used * as replacement * */ public void replace(String handlerName, ChannelHandler handler) { if (ctx == null) { throw new IllegalStateException( "Replace cann only be called once the FrameDecoder is added to the ChannelPipeline"); } ChannelPipeline pipeline = ctx.getPipeline(); pipeline.addAfter(ctx.getName(), handlerName, handler); try { if (cumulation != null) { Channels.fireMessageReceived(ctx, cumulation.readBytes(actualReadableBytes())); } } finally { pipeline.remove(this); } }
@Override public void handleUpstream(final ChannelHandlerContext ctx, final ChannelEvent ce) throws Exception { if (!handshakeDone || !rtmpe || !(ce instanceof MessageEvent)) { super.handleUpstream(ctx, ce); return; } final MessageEvent me = (MessageEvent) ce; if(me.getMessage() instanceof RtmpPublisher.Event) { super.handleUpstream(ctx, ce); return; } final ChannelBuffer in = (ChannelBuffer) ((MessageEvent) ce).getMessage(); handshake.cipherUpdateIn(in); Channels.fireMessageReceived(ctx, in); }
protected ChannelBuffer updateCumulation(ChannelHandlerContext ctx, ChannelBuffer input) { ChannelBuffer newCumulation; int readableBytes = input.readableBytes(); if (readableBytes > 0) { int inputCapacity = input.capacity(); // If input.readableBytes() == input.capacity() (i.e. input is full), // there's nothing to save from creating a new cumulation buffer // even if input.capacity() exceeds the threshold, because the new cumulation // buffer will have the same capacity and content with input. if (readableBytes < inputCapacity && inputCapacity > copyThreshold) { // At least one byte was consumed by callDecode() and input.capacity() // exceeded the threshold. cumulation = newCumulation = newCumulationBuffer(ctx, input.readableBytes()); cumulation.writeBytes(input); } else { // Nothing was consumed by callDecode() or input.capacity() did not // exceed the threshold. if (input.readerIndex() != 0) { cumulation = newCumulation = input.slice(); } else { cumulation = newCumulation = input; } } } else { cumulation = newCumulation = null; } return newCumulation; }
@Override public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { processChannelClosed(ctx); super.channelClosed(ctx, e); }
@Override public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception { Throwable t = e.getCause(); if (t instanceof IOException) { processChannelClosed(ctx); } else if (t instanceof NotYetConnectedException) { processChannelClosed(ctx); } super.exceptionCaught(ctx, e); }
@Override public void handleUpstream(final ChannelHandlerContext ctx, final ChannelEvent ce) throws Exception { if (!handshakeDone || !rtmpe || !(ce instanceof MessageEvent)) { super.handleUpstream(ctx, ce); return; } final MessageEvent me = (MessageEvent) ce; if(me.getMessage() instanceof RtmpPublisher.Event) { super.handleUpstream(ctx, ce); return; } final ChannelBuffer in = (ChannelBuffer) ((MessageEvent) ce).getMessage(); handshake.cipherUpdateIn(in); Channels.fireMessageReceived(ctx, in); }
@Override protected synchronized ChannelBuffer newCumulationBuffer(ChannelHandlerContext ctx, int minimumCapacity) { @SuppressWarnings("unchecked") Map<String, Object> attachment = (Map<String, Object>) ctx.getAttachment(); int size = (Integer) attachment.get(NEEDED_DATA); if (inMemorySizeLimit > 0) { return ChannelBuffers.dynamicBuffer(Math.min(size, inMemorySizeLimit), ctx.getChannel().getConfig().getBufferFactory()); } else { if (size > 0) { return ChannelBuffers.dynamicBuffer(size, ctx.getChannel().getConfig().getBufferFactory()); } return super.newCumulationBuffer(ctx, minimumCapacity); } }
@Override public void beforeAdd(ChannelHandlerContext ctx) throws Exception { super.beforeAdd(ctx); this.ctx = ctx; }
@Override public void handleUpstream(final ChannelHandlerContext ctx, final ChannelEvent ce) throws Exception { if (!handshakeDone || !rtmpe || !(ce instanceof MessageEvent)) { super.handleUpstream(ctx, ce); return; } final MessageEvent me = (MessageEvent) ce; if(me.getMessage() instanceof RtmpPublisher.Event) { super.handleUpstream(ctx, ce); return; } final ChannelBuffer in = (ChannelBuffer) ((MessageEvent) ce).getMessage(); handshake.cipherUpdateIn(in); Channels.fireMessageReceived(ctx, in); }