netty5/transport/src/main/java/io/netty/channel/ChannelHandlerContext.java

345 lines
14 KiB
Java
Raw Normal View History

/*
2012-06-04 22:31:44 +02:00
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
2012-06-04 22:31:44 +02:00
* http://www.apache.org/licenses/LICENSE-2.0
*
2009-08-28 09:15:49 +02:00
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
2009-08-28 09:15:49 +02:00
* License for the specific language governing permissions and limitations
* under the License.
*/
2011-12-09 04:38:59 +01:00
package io.netty.channel;
2009-09-10 06:25:05 +02:00
import io.netty.buffer.ByteBuf;
import io.netty.buffer.MessageBuf;
2012-12-21 07:13:31 +01:00
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.netty.util.AttributeMap;
import java.nio.channels.Channels;
import java.util.Set;
/**
* Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
2012-12-21 07:13:31 +01:00
* and other handlers. A handler can notify the next {@link ChannelHandler} in the {@link ChannelPipeline},
* modify the {@link ChannelPipeline} it belongs to dynamically.
2010-02-17 09:22:45 +01:00
*
2012-12-21 07:13:31 +01:00
* <h3>Notify</h3>
2010-02-17 09:22:45 +01:00
*
2012-12-21 07:13:31 +01:00
* You can notify the closest handler in the
* same {@link ChannelPipeline} by calling one of the various methods which are listed in {@link ChannelInboundInvoker}
* and {@link ChannelOutboundInvoker}. Please refer to {@link ChannelPipeline} to understand how an event flows.
2010-02-17 09:22:45 +01:00
*
* <h3>Modifying a pipeline</h3>
*
* You can get the {@link ChannelPipeline} your handler belongs to by calling
2012-12-21 07:13:31 +01:00
* {@link #pipeline()}. A non-trivial application could insert, remove, or
2010-02-17 09:22:45 +01:00
* replace handlers in the pipeline dynamically in runtime.
*
* <h3>Retrieving for later use</h3>
*
* You can keep the {@link ChannelHandlerContext} for later use, such as
* triggering an event outside the handler methods, even from a different thread.
* <pre>
2012-12-21 07:13:31 +01:00
* public class MyHandler extends {@link ChannelHandlerAdapter} {
2010-02-17 09:22:45 +01:00
*
* <b>private {@link ChannelHandlerContext} ctx;</b>
2010-02-17 09:22:45 +01:00
*
* public void beforeAdd({@link ChannelHandlerContext} ctx) {
* <b>this.ctx = ctx;</b>
2010-02-17 09:22:45 +01:00
* }
*
* public void login(String username, password) {
2012-12-21 07:13:31 +01:00
* ctx.write(new LoginMessage(username, password));
2010-02-17 09:22:45 +01:00
* }
* ...
* }
2009-04-28 15:35:55 +02:00
* </pre>
2010-02-17 09:22:45 +01:00
*
2010-02-17 09:28:45 +01:00
* <h3>Storing stateful information</h3>
*
2012-12-21 07:13:31 +01:00
* {@link #attr(AttributeKey)} allow you to
2010-02-17 09:28:45 +01:00
* store and access stateful information that is related with a handler and its
* context. Please refer to {@link ChannelHandler} to learn various recommended
* ways to manage stateful information.
*
2010-02-17 09:22:45 +01:00
* <h3>A handler can have more than one context</h3>
*
2009-04-28 15:35:55 +02:00
* Please note that a {@link ChannelHandler} instance can be added to more than
* one {@link ChannelPipeline}. It means a single {@link ChannelHandler}
* instance can have more than one {@link ChannelHandlerContext} and therefore
2009-06-17 11:13:10 +02:00
* the single instance can be invoked with different
* {@link ChannelHandlerContext}s if it is added to one or more
* {@link ChannelPipeline}s more than once.
* <p>
* For example, the following handler will have as many independent attachments
* as how many times it is added to pipelines, regardless if it is added to the
* same pipeline multiple times or added to different pipelines multiple times:
2009-04-28 15:35:55 +02:00
* <pre>
2012-12-21 07:13:31 +01:00
* public class FactorialHandler extends {@link ChannelInboundMessageHandlerAdapter}&lt{@link Integer}&gt {
*
* private final {@link AttributeKey}&lt{@link Integer}&gt counter =
* new {@link AttributeKey}&lt{@link Integer}&gt("counter");
*
* // This handler will receive a sequence of increasing integers starting
* // from 1.
2010-02-02 03:00:04 +01:00
* {@code @Override}
2012-12-21 07:13:31 +01:00
* public void messageReceived({@link ChannelHandlerContext} ctx, {@link Integer} integer) {
2012-12-21 07:35:42 +01:00
* {@link Attribute}&lt{@link Integer}&gt attr = ctx.getAttr(counter);
2012-12-21 07:13:31 +01:00
* Integer a = ctx.getAttr(counter).get();
2009-04-28 15:35:55 +02:00
*
* if (a == null) {
* a = 1;
2009-04-28 15:35:55 +02:00
* }
*
2012-12-21 07:13:31 +01:00
* attr.set(a * integer));
2009-04-28 15:35:55 +02:00
* }
* }
*
* // Different context objects are given to "f1", "f2", "f3", and "f4" even if
2009-04-28 16:41:48 +02:00
* // they refer to the same handler instance. Because the FactorialHandler
* // stores its state in a context object (as an attachment), the factorial is
2009-04-28 16:43:20 +02:00
* // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
* FactorialHandler fh = new FactorialHandler();
*
2010-02-02 03:00:04 +01:00
* {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
* p1.addLast("f1", fh);
* p1.addLast("f2", fh);
*
2010-02-02 03:00:04 +01:00
* {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
* p2.addLast("f3", fh);
* p2.addLast("f4", fh);
* </pre>
*
2009-06-17 11:13:10 +02:00
* <h3>Additional resources worth reading</h3>
* <p>
2012-12-21 07:13:31 +01:00
* Please refer to the {@link ChannelHandler}, and
* {@link ChannelPipeline} to find out more about inbound and outbound operations,
* what fundamental differences they have, how they flow in a pipeline, and how to handle
* the operation in your application.
2011-12-09 04:38:59 +01:00
* @apiviz.owns io.netty.channel.ChannelHandler
*/
public interface ChannelHandlerContext
ByteBufAllocator API w/ ByteBuf perf improvements This commit introduces a new API for ByteBuf allocation which fixes issue #643 along with refactoring of ByteBuf for simplicity and better performance. (see #62) A user can configure the ByteBufAllocator of a Channel via ChannelOption.ALLOCATOR or ChannelConfig.get/setAllocator(). The default allocator is currently UnpooledByteBufAllocator.HEAP_BY_DEFAULT. To allocate a buffer, do not use Unpooled anymore. do the following: ctx.alloc().buffer(...); // allocator chooses the buffer type. ctx.alloc().heapBuffer(...); ctx.alloc().directBuffer(...); To deallocate a buffer, use the unsafe free() operation: ((UnsafeByteBuf) buf).free(); The following is the list of the relevant changes: - Add ChannelInboundHandler.freeInboundBuffer() and ChannelOutboundHandler.freeOutboundBuffer() to let a user free the buffer he or she allocated. ChannelHandler adapter classes implement is already, so most users won't need to call free() by themselves. freeIn/OutboundBuffer() methods are invoked when a Channel is closed and deregistered. - All ByteBuf by contract must implement UnsafeByteBuf. To access an unsafe operation: ((UnsafeByteBuf) buf).internalNioBuffer() - Replace WrappedByteBuf and ByteBuf.Unsafe with UnsafeByteBuf to simplify overall class hierarchy and to avoid unnecesary instantiation of Unsafe instances on an unsafe operation. - Remove buffer reference counting which is confusing - Instantiate SwappedByteBuf lazily to avoid instantiation cost - Rename ChannelFutureFactory to ChannelPropertyAccess and move common methods between Channel and ChannelHandlerContext there. Also made it package-private to hide it from a user. - Remove unused unsafe operations such as newBuffer() - Add DetectionUtil.canFreeDirectBuffer() so that an allocator decides which buffer type to use safely
2012-11-15 22:04:37 +01:00
extends AttributeMap, ChannelPropertyAccess,
ChannelInboundInvoker, ChannelOutboundInvoker {
2012-08-28 01:14:05 +02:00
/**
* Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}.
*/
Channel channel();
2012-08-28 01:14:05 +02:00
/**
* The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly
* submit tasks that get executed in the event loop. For more informations please refer to the
* {@link EventExecutor} javadocs.
*/
EventExecutor executor();
2012-08-28 01:14:05 +02:00
/**
* The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler}
* was added to the {@link ChannelPipeline}. This name can also be used to access the registered
* {@link ChannelHandler} from the {@link ChannelPipeline}.
*/
String name();
2012-08-28 01:14:05 +02:00
/**
* The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}.
*/
ChannelHandler handler();
/**
* Return an unmodifiable {@link Set} that contains all the {@link ChannelHandlerType}s which are handled by this
* context and the {@link ChannelHandler} it belongs to.
*/
Set<ChannelHandlerType> types();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the {@link ChannelHandlerContext} has an {@link ByteBuf} bound for inbound
2012-08-28 01:14:05 +02:00
* which can be used.
*/
boolean hasInboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the {@link ChannelHandlerContext} has a {@link MessageBuf} bound for inbound
2012-08-28 01:14:05 +02:00
* which can be used.
*/
boolean hasInboundMessageBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the bound {@link ByteBuf} for inbound data if {@link #hasInboundByteBuffer()} returned
* {@code true}. If {@link #hasInboundByteBuffer()} returned {@code false} it will throw a
* {@link UnsupportedOperationException}.
* <p/>
* This method can only be called from within the event-loop, otherwise it will throw an
* {@link IllegalStateException}.
2012-08-28 01:14:05 +02:00
*/
ByteBuf inboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the bound {@link MessageBuf} for inbound data if {@link #hasInboundMessageBuffer()} returned
* {@code true}. If {@link #hasInboundMessageBuffer()} returned {@code false} it will throw a
2012-08-28 01:14:05 +02:00
* {@link UnsupportedOperationException}.
* <p/>
* This method can only be called from within the event-loop, otherwise it will throw an
* {@link IllegalStateException}.
2012-08-28 01:14:05 +02:00
*/
<T> MessageBuf<T> inboundMessageBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the {@link ChannelHandlerContext} has an {@link ByteBuf} bound for outbound
2012-08-28 01:14:05 +02:00
* data which can be used.
*
*/
boolean hasOutboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the {@link ChannelHandlerContext} has a {@link MessageBuf} bound for outbound
2012-08-28 01:14:05 +02:00
* which can be used.
*/
boolean hasOutboundMessageBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the bound {@link ByteBuf} for outbound data if {@link #hasOutboundByteBuffer()} returned
* {@code true}. If {@link #hasOutboundByteBuffer()} returned {@code false} it will throw
2012-08-28 01:14:05 +02:00
* a {@link UnsupportedOperationException}.
* <p/>
* This method can only be called from within the event-loop, otherwise it will throw an
* {@link IllegalStateException}.
2012-08-28 01:14:05 +02:00
*/
ByteBuf outboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the bound {@link MessageBuf} for outbound data if {@link #hasOutboundMessageBuffer()} returned
* {@code true}. If {@link #hasOutboundMessageBuffer()} returned {@code false} it will throw a
* {@link UnsupportedOperationException}.
* <p/>
* This method can only be called from within the event-loop, otherwise it will throw an
* {@link IllegalStateException}.
2012-08-28 01:14:05 +02:00
*/
<T> MessageBuf<T> outboundMessageBuffer();
/**
* Replaces the inbound byte buffer with the given buffer. This returns the
* old buffer, so any readable bytes can be handled appropriately by the caller.
* <p>
* Be cautious with caching {@link #inboundByteBuffer()} as it may change as a result of this
* method. For example, instead of extending {@link io.netty.handler.codec.ByteToMessageDecoder},
* extend what that class does (currently, {@link ChannelInboundHandlerAdapter} and
* {@link ChannelInboundByteHandler}. In other words, implementing your own
* {@link ChannelInboundHandlerAdapter#inboundBufferUpdated}/{@link ChannelStateHandler#inboundBufferUpdated}
* will help guarantee a replaced buffer won't be missed.</p>
*
* @param newInboundByteBuf the new inbound byte buffer
* @return the old buffer.
* @throws NullPointerException if the argument is {@code null}.
*/
ByteBuf replaceInboundByteBuffer(ByteBuf newInboundByteBuf);
/**
* Replaces the inbound message buffer with the given buffer. This returns the
* old buffer, so any pending messages can be handled appropriately by the caller.
* <p>
* Be cautious with caching {@link #inboundMessageBuffer()} as it may change as a result of this
* method. For example, instead of extending {@link io.netty.handler.codec.MessageToMessageDecoder},
* extend what that class does (currently, {@link ChannelInboundHandlerAdapter} and
* {@link ChannelInboundMessageHandler}. In other words, implementing your own
* {@link ChannelInboundHandlerAdapter#inboundBufferUpdated}/{@link ChannelStateHandler#inboundBufferUpdated}
* will help guarantee a replaced buffer won't be missed.</p>
*
* @param newInboundMsgBuf the new inbound message buffer
* @return the old buffer.
* @throws NullPointerException if the argument is {@code null}.
*/
<T> MessageBuf<T> replaceInboundMessageBuffer(MessageBuf<T> newInboundMsgBuf);
/**
* Replaces the outbound byte buffer with the given buffer. This returns the
* old buffer, so any readable bytes can be handled appropriately by the caller.
* <p>
* Be cautious with caching {@link #outboundByteBuffer()} as it may change as a result of this
* method. For example, instead of extending {@link io.netty.handler.codec.ByteToByteEncoder},
* extend what that class does (currently, {@link ChannelOutboundByteHandlerAdapter}).
* In other words, implementing your own
* {@link ChannelOutboundHandlerAdapter#flush}/{@link ChannelOperationHandler#flush}
* will help guarantee a replaced buffer won't be missed.</p>
*
* @param newOutboundByteBuf the new inbound byte buffer
* @return the old buffer.
* @throws NullPointerException if the argument is {@code null}.
*/
ByteBuf replaceOutboundByteBuffer(ByteBuf newOutboundByteBuf);
/**
* Replaces the outbound message buffer with the given buffer. This returns the
* old buffer, so any pending messages can be handled appropriately by the caller.
* <p>
* Be cautious with caching {@link #outboundMessageBuffer()} as it may change as a result of this
* method. For example, instead of extending {@link io.netty.handler.codec.MessageToByteEncoder}
* or {@link io.netty.handler.codec.MessageToMessageEncoder}, extend what these classes do (currently,
* {@link ChannelOutboundMessageHandlerAdapter}. In other words, implementing your own
* {@link ChannelOutboundHandlerAdapter#flush}/{@link ChannelOperationHandler#flush}
* will help guarantee a replaced buffer won't be missed.</p>
*
* @param newOutboundMsgBuf the new inbound message buffer
* @return the old buffer.
* @throws NullPointerException if the argument is {@code null}.
*/
<T> MessageBuf<T> replaceOutboundMessageBuffer(MessageBuf<T> newOutboundMsgBuf);
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the next {@link ChannelHandlerContext} has a {@link ByteBuf} for handling
2012-08-28 01:14:05 +02:00
* inbound data.
*/
boolean hasNextInboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the next {@link ChannelHandlerContext} has a {@link MessageBuf} for handling
2012-08-28 01:14:05 +02:00
* inbound data.
*/
boolean hasNextInboundMessageBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the {@link ByteBuf} of the next {@link ChannelHandlerContext} if {@link #hasNextInboundByteBuffer()}
* returned {@code true}, otherwise a {@link UnsupportedOperationException} is thrown.
2012-08-28 01:14:05 +02:00
*/
ByteBuf nextInboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the {@link MessageBuf} of the next {@link ChannelHandlerContext} if
* {@link #hasNextInboundMessageBuffer()} returned {@code true}, otherwise a
2012-08-28 01:14:05 +02:00
* {@link UnsupportedOperationException} is thrown.
*/
MessageBuf<Object> nextInboundMessageBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the next {@link ChannelHandlerContext} has a {@link ByteBuf} for handling outbound
2012-08-28 01:14:05 +02:00
* data.
*/
boolean hasNextOutboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return {@code true} if the next {@link ChannelHandlerContext} has a {@link MessageBuf} for handling
2012-08-28 01:14:05 +02:00
* outbound data.
*/
boolean hasNextOutboundMessageBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the {@link ByteBuf} of the next {@link ChannelHandlerContext} if {@link #hasNextOutboundByteBuffer()}
* returned {@code true}, otherwise a {@link UnsupportedOperationException} is thrown.
2012-08-28 01:14:05 +02:00
*/
ByteBuf nextOutboundByteBuffer();
2012-08-28 01:14:05 +02:00
/**
* Return the {@link MessageBuf} of the next {@link ChannelHandlerContext} if
* {@link #hasNextOutboundMessageBuffer()} returned {@code true}, otherwise a
2012-08-28 01:14:05 +02:00
* {@link UnsupportedOperationException} is thrown.
*/
MessageBuf<Object> nextOutboundMessageBuffer();
2009-08-28 09:15:49 +02:00
}