View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel;
17  
18  import io.netty.util.Attribute;
19  import io.netty.util.AttributeKey;
20  
21  import java.lang.annotation.Documented;
22  import java.lang.annotation.ElementType;
23  import java.lang.annotation.Inherited;
24  import java.lang.annotation.Retention;
25  import java.lang.annotation.RetentionPolicy;
26  import java.lang.annotation.Target;
27  import java.net.SocketAddress;
28  
29  /**
30   * Handles an I/O event or intercepts an I/O operation, and forwards it to its next handler in
31   * its {@link ChannelPipeline}.
32   *
33   * <h3>Extend {@link ChannelHandlerAdapter} instead</h3>
34   * <p>
35   * Because this interface has many methods to implement, you might want to extend {@link ChannelHandlerAdapter}
36   * instead.
37   * </p>
38   *
39   * <h3>The context object</h3>
40   * <p>
41   * A {@link ChannelHandler} is provided with a {@link ChannelHandlerContext}
42   * object.  A {@link ChannelHandler} is supposed to interact with the
43   * {@link ChannelPipeline} it belongs to via a context object.  Using the
44   * context object, the {@link ChannelHandler} can pass events upstream or
45   * downstream, modify the pipeline dynamically, or store the information
46   * (using {@link AttributeKey}s) which is specific to the handler.
47   *
48   * <h3>State management</h3>
49   *
50   * A {@link ChannelHandler} often needs to store some stateful information.
51   * The simplest and recommended approach is to use member variables:
52   * <pre>
53   * public interface Message {
54   *     // your methods here
55   * }
56   *
57   * public class DataServerHandler extends {@link SimpleChannelInboundHandler}&lt;Message&gt; {
58   *
59   *     <b>private boolean loggedIn;</b>
60   *
61   *     {@code @Override}
62   *     protected void messageReceived({@link ChannelHandlerContext} ctx, Message message) {
63   *         {@link Channel} ch = e.getChannel();
64   *         if (message instanceof LoginMessage) {
65   *             authenticate((LoginMessage) message);
66   *             <b>loggedIn = true;</b>
67   *         } else (message instanceof GetDataMessage) {
68   *             if (<b>loggedIn</b>) {
69   *                 ch.write(fetchSecret((GetDataMessage) message));
70   *             } else {
71   *                 fail();
72   *             }
73   *         }
74   *     }
75   *     ...
76   * }
77   * </pre>
78   * Because the handler instance has a state variable which is dedicated to
79   * one connection, you have to create a new handler instance for each new
80   * channel to avoid a race condition where a unauthenticated client can get
81   * the confidential information:
82   * <pre>
83   * // Create a new handler instance per channel.
84   * // See {@link ChannelInitializer#initChannel(Channel)}.
85   * public class DataServerInitializer extends {@link ChannelInitializer}&lt;{@link Channel}&gt; {
86   *     {@code @Override}
87   *     public void initChannel({@link Channel} channel) {
88   *         channel.pipeline().addLast("handler", <b>new DataServerHandler()</b>);
89   *     }
90   * }
91   *
92   * </pre>
93   *
94   * <h4>Using {@link AttributeKey}s</h4>
95   *
96   * Although it's recommended to use member variables to store the state of a
97   * handler, for some reason you might not want to create many handler instances.
98   * In such a case, you can use {@link AttributeKey}s which are attached to the
99   * {@link ChannelHandlerContext}:
100  * <pre>
101  * public interface Message {
102  *     // your methods here
103  * }
104  *
105  * {@code @Sharable}
106  * public class DataServerHandler extends {@link SimpleChannelInboundHandler}&lt;Message&gt; {
107  *     private final {@link AttributeKey}&lt;{@link Boolean}&gt; auth =
108  *           {@link AttributeKey#valueOf(String) AttributeKey.valueOf("auth")};
109  *
110  *     {@code @Override}
111  *     protected void messageReceived({@link ChannelHandlerContext} ctx, Message message) {
112  *         {@link Attribute}&lt;{@link Boolean}&gt; attr = ctx.attr(auth);
113  *         {@link Channel} ch = ctx.channel();
114  *
115  *         if (message instanceof LoginMessage) {
116  *             authenticate((LoginMessage) o);
117  *             <b>attr.set(true)</b>;
118  *         } else (message instanceof GetDataMessage) {
119  *             if (<b>Boolean.TRUE.equals(attr.get())</b>) {
120  *                 ch.write(fetchSecret((GetDataMessage) o));
121  *             } else {
122  *                 fail();
123  *             }
124  *         }
125  *     }
126  *     ...
127  * }
128  * </pre>
129  * Now that the state of the handler is attached to the {@link ChannelHandlerContext}, you can add the
130  * same handler instance to different pipelines:
131  * <pre>
132  * public class DataServerInitializer extends {@link ChannelInitializer}&lt;{@link Channel}&gt; {
133  *
134  *     private static final DataServerHandler <b>SHARED</b> = new DataServerHandler();
135  *
136  *     {@code @Override}
137  *     public void initChannel({@link Channel} channel) {
138  *         channel.pipeline().addLast("handler", <b>SHARED</b>);
139  *     }
140  * }
141  * </pre>
142  *
143  *
144  * <h4>The {@code @Sharable} annotation</h4>
145  * <p>
146  * In the example above which used an {@link AttributeKey},
147  * you might have noticed the {@code @Sharable} annotation.
148  * <p>
149  * If a {@link ChannelHandler} is annotated with the {@code @Sharable}
150  * annotation, it means you can create an instance of the handler just once and
151  * add it to one or more {@link ChannelPipeline}s multiple times without
152  * a race condition.
153  * <p>
154  * If this annotation is not specified, you have to create a new handler
155  * instance every time you add it to a pipeline because it has unshared state
156  * such as member variables.
157  * <p>
158  * This annotation is provided for documentation purpose, just like
159  * <a href="http://www.javaconcurrencyinpractice.com/annotations/doc/">the JCIP annotations</a>.
160  *
161  * <h3>Additional resources worth reading</h3>
162  * <p>
163  * Please refer to the {@link ChannelHandler}, and
164  * {@link ChannelPipeline} to find out more about inbound and outbound operations,
165  * what fundamental differences they have, how they flow in a  pipeline,  and how to handle
166  * the operation in your application.
167  */
168 public interface ChannelHandler {
169 
170     ////////////////////////////////
171     // Handler life cycle methods //
172     ////////////////////////////////
173 
174     /**
175      * Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events.
176      */
177     void handlerAdded(ChannelHandlerContext ctx) throws Exception;
178 
179     /**
180      * Gets called after the {@link ChannelHandler} was removed from the actual context and it doesn't handle events
181      * anymore.
182      */
183     void handlerRemoved(ChannelHandlerContext ctx) throws Exception;
184 
185     ///////////////////////////////////
186     // Inbound event handler methods //
187     ///////////////////////////////////
188 
189     /**
190      * Gets called if a {@link Throwable} was thrown.
191      */
192     void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
193 
194     /**
195      * The {@link Channel} of the {@link ChannelHandlerContext} was registered with its {@link EventLoop}
196      */
197     void channelRegistered(ChannelHandlerContext ctx) throws Exception;
198 
199     /**
200      * The {@link Channel} of the {@link ChannelHandlerContext} was unregistered from its {@link EventLoop}
201      */
202     void channelUnregistered(ChannelHandlerContext ctx) throws Exception;
203 
204     /**
205      * The {@link Channel} of the {@link ChannelHandlerContext} is now active
206      */
207     void channelActive(ChannelHandlerContext ctx) throws Exception;
208 
209     /**
210      * The {@link Channel} of the {@link ChannelHandlerContext} was registered is now inactive and reached its
211      * end of lifetime.
212      */
213     void channelInactive(ChannelHandlerContext ctx) throws Exception;
214 
215     /**
216      * Invoked when the current {@link Channel} has read a message from the peer.
217      */
218     void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;
219 
220     /**
221      * Invoked when the last message read by the current read operation has been consumed by
222      * {@link #channelRead(ChannelHandlerContext, Object)}.  If {@link ChannelOption#AUTO_READ} is off, no further
223      * attempt to read an inbound data from the current {@link Channel} will be made until
224      * {@link ChannelHandlerContext#read()} is called.
225      */
226     void channelReadComplete(ChannelHandlerContext ctx) throws Exception;
227 
228     /**
229      * Gets called if an user event was triggered.
230      */
231     void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
232 
233     /**
234      * Gets called once the writable state of a {@link Channel} changed. You can check the state with
235      * {@link Channel#isWritable()}.
236      */
237     void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception;
238 
239     ////////////////////////////////////
240     // Outbound event handler methods //
241     ////////////////////////////////////
242 
243     /**
244      * Called once a bind operation is made.
245      *
246      * @param ctx           the {@link ChannelHandlerContext} for which the bind operation is made
247      * @param localAddress  the {@link java.net.SocketAddress} to which it should bound
248      * @param promise       the {@link ChannelPromise} to notify once the operation completes
249      * @throws Exception    thrown if an error accour
250      */
251     void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception;
252 
253     /**
254      * Called once a connect operation is made.
255      *
256      * @param ctx               the {@link ChannelHandlerContext} for which the connect operation is made
257      * @param remoteAddress     the {@link SocketAddress} to which it should connect
258      * @param localAddress      the {@link SocketAddress} which is used as source on connect
259      * @param promise           the {@link ChannelPromise} to notify once the operation completes
260      * @throws Exception        thrown if an error accour
261      */
262     void connect(
263             ChannelHandlerContext ctx,
264             SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) throws Exception;
265 
266     /**
267      * Called once a disconnect operation is made.
268      *
269      * @param ctx               the {@link ChannelHandlerContext} for which the disconnect operation is made
270      * @param promise           the {@link ChannelPromise} to notify once the operation completes
271      * @throws Exception        thrown if an error accour
272      */
273     void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
274 
275     /**
276      * Called once a close operation is made.
277      *
278      * @param ctx               the {@link ChannelHandlerContext} for which the close operation is made
279      * @param promise           the {@link ChannelPromise} to notify once the operation completes
280      * @throws Exception        thrown if an error accour
281      */
282     void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
283 
284     /**
285      * Called once a deregister operation is made from the current registered {@link EventLoop}.
286      *
287      * @param ctx               the {@link ChannelHandlerContext} for which the close operation is made
288      * @param promise           the {@link ChannelPromise} to notify once the operation completes
289      * @throws Exception        thrown if an error accour
290      */
291     void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception;
292 
293     /**
294      * Intercepts {@link ChannelHandlerContext#read()}.
295      */
296     void read(ChannelHandlerContext ctx) throws Exception;
297 
298     /**
299      * Called once a write operation is made. The write operation will write the messages through the
300      * {@link ChannelPipeline}. Those are then ready to be flushed to the actual {@link Channel} once
301      * {@link Channel#flush()} is called
302      *
303      * @param ctx               the {@link ChannelHandlerContext} for which the write operation is made
304      * @param msg               the message to write
305      * @param promise           the {@link ChannelPromise} to notify once the operation completes
306      * @throws Exception        thrown if an error accour
307      */
308     void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception;
309 
310     /**
311      * Called once a flush operation is made. The flush operation will try to flush out all previous written messages
312      * that are pending.
313      *
314      * @param ctx               the {@link ChannelHandlerContext} for which the flush operation is made
315      * @throws Exception        thrown if an error accour
316      */
317     void flush(ChannelHandlerContext ctx) throws Exception;
318 
319     /////////////////
320     // Annotations //
321     /////////////////
322 
323     /**
324      * Indicates that the same instance of the annotated {@link ChannelHandler}
325      * can be added to one or more {@link ChannelPipeline}s multiple times
326      * without a race condition.
327      * <p>
328      * If this annotation is not specified, you have to create a new handler
329      * instance every time you add it to a pipeline because it has unshared
330      * state such as member variables.
331      * <p>
332      * This annotation is provided for documentation purpose, just like
333      * <a href="http://www.javaconcurrencyinpractice.com/annotations/doc/">the JCIP annotations</a>.
334      */
335     @Inherited
336     @Documented
337     @Target(ElementType.TYPE)
338     @Retention(RetentionPolicy.RUNTIME)
339     @interface Sharable {
340         // no value
341     }
342 
343     /**
344      * Indicates that the annotated event handler method in {@link ChannelHandler} will not be invoked by
345      * {@link ChannelPipeline}.  This annotation is only useful when your handler method implementation
346      * only passes the event through to the next handler, like the following:
347      *
348      * <pre>
349      * {@code @Skip}
350      * {@code @Override}
351      * public void channelActive({@link ChannelHandlerContext} ctx) {
352      *     ctx.fireChannelActive(); // do nothing but passing through to the next handler
353      * }
354      * </pre>
355      *
356      * {@link #handlerAdded(ChannelHandlerContext)} and {@link #handlerRemoved(ChannelHandlerContext)} are not able to
357      * pass the event through to the next handler, so they must do nothing when annotated.
358      *
359      * <pre>
360      * {@code @Skip}
361      * {@code @Override}
362      * public void handlerAdded({@link ChannelHandlerContext} ctx) {
363      *     // do nothing
364      * }
365      * </pre>
366      *
367      * <p>
368      * Note that this annotation is not {@linkplain Inherited inherited}.  If you override a method annotated with
369      * {@link Skip}, it will not be skipped anymore.  Similarly, you can override a method not annotated with
370      * {@link Skip} and simply pass the event through to the next handler, which reverses the behavior of the
371      * supertype.
372      * </p>
373      */
374     @Target(ElementType.METHOD)
375     @Retention(RetentionPolicy.RUNTIME)
376     @interface Skip {
377         // no value
378     }
379 }