查看本类的 API文档回源码主页即时通讯网 - 即时通讯开发者社区!
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  
19  import io.netty.buffer.ByteBuf;
20  import io.netty.buffer.ByteBufAllocator;
21  import io.netty.util.AttributeKey;
22  import io.netty.util.AttributeMap;
23  import io.netty.util.concurrent.EventExecutor;
24  import io.netty.util.concurrent.FutureListener;
25  
26  import java.net.ConnectException;
27  import java.net.SocketAddress;
28  import java.nio.channels.Channels;
29  
30  /**
31   * Enables a {@link ChannelHandler} to interact with its {@link ChannelPipeline}
32   * and other handlers.  A handler can notify the next {@link ChannelHandler} in the {@link ChannelPipeline},
33   * modify the {@link ChannelPipeline} it belongs to dynamically.
34   *
35   * <h3>Notify</h3>
36   *
37   * You can notify the closest handler in the
38   * same {@link ChannelPipeline} by calling one of the various methods provided here.
39   * Please refer to {@link ChannelPipeline} to understand how an event flows.
40   *
41   * <h3>Modifying a pipeline</h3>
42   *
43   * You can get the {@link ChannelPipeline} your handler belongs to by calling
44   * {@link #pipeline()}.  A non-trivial application could insert, remove, or
45   * replace handlers in the pipeline dynamically at runtime.
46   *
47   * <h3>Retrieving for later use</h3>
48   *
49   * You can keep the {@link ChannelHandlerContext} for later use, such as
50   * triggering an event outside the handler methods, even from a different thread.
51   * <pre>
52   * public class MyHandler extends {@link ChannelDuplexHandler} {
53   *
54   *     <b>private {@link ChannelHandlerContext} ctx;</b>
55   *
56   *     public void beforeAdd({@link ChannelHandlerContext} ctx) {
57   *         <b>this.ctx = ctx;</b>
58   *     }
59   *
60   *     public void login(String username, password) {
61   *         ctx.write(new LoginMessage(username, password));
62   *     }
63   *     ...
64   * }
65   * </pre>
66   *
67   * <h3>Storing stateful information</h3>
68   *
69   * {@link #attr(AttributeKey)} allow you to
70   * store and access stateful information that is related with a handler and its
71   * context.  Please refer to {@link ChannelHandler} to learn various recommended
72   * ways to manage stateful information.
73   *
74   * <h3>A handler can have more than one context</h3>
75   *
76   * Please note that a {@link ChannelHandler} instance can be added to more than
77   * one {@link ChannelPipeline}.  It means a single {@link ChannelHandler}
78   * instance can have more than one {@link ChannelHandlerContext} and therefore
79   * the single instance can be invoked with different
80   * {@link ChannelHandlerContext}s if it is added to one or more
81   * {@link ChannelPipeline}s more than once.
82   * <p>
83   * For example, the following handler will have as many independent {@link AttributeKey}s
84   * as how many times it is added to pipelines, regardless if it is added to the
85   * same pipeline multiple times or added to different pipelines multiple times:
86   * <pre>
87   * public class FactorialHandler extends {@link ChannelInboundHandlerAdapter}&lt{@link Integer}&gt {
88   *
89   *   private final {@link AttributeKey}&lt;{@link Integer}&gt; counter =
90   *           new {@link AttributeKey}&lt;{@link Integer}&gt;("counter");
91   *
92   *   // This handler will receive a sequence of increasing integers starting
93   *   // from 1.
94   *   {@code @Override}
95   *   public void channelRead({@link ChannelHandlerContext} ctx, Object msg) {
96   *     Integer a = ctx.attr(counter).get();
97   *
98   *     if (a == null) {
99   *       a = 1;
100  *     }
101  *
102  *     attr.set(a * integer));
103  *   }
104  * }
105  *
106  * // Different context objects are given to "f1", "f2", "f3", and "f4" even if
107  * // they refer to the same handler instance.  Because the FactorialHandler
108  * // stores its state in a context object (as an (using an {@link AttributeKey}), the factorial is
109  * // calculated correctly 4 times once the two pipelines (p1 and p2) are active.
110  * FactorialHandler fh = new FactorialHandler();
111  *
112  * {@link ChannelPipeline} p1 = {@link Channels}.pipeline();
113  * p1.addLast("f1", fh);
114  * p1.addLast("f2", fh);
115  *
116  * {@link ChannelPipeline} p2 = {@link Channels}.pipeline();
117  * p2.addLast("f3", fh);
118  * p2.addLast("f4", fh);
119  * </pre>
120  *
121  * <h3>Additional resources worth reading</h3>
122  * <p>
123  * Please refer to the {@link ChannelHandler}, and
124  * {@link ChannelPipeline} to find out more about inbound and outbound operations,
125  * what fundamental differences they have, how they flow in a  pipeline,  and how to handle
126  * the operation in your application.
127  */
128 public interface ChannelHandlerContext
129          extends AttributeMap {
130 
131     /**
132      * Return the {@link Channel} which is bound to the {@link ChannelHandlerContext}.
133      */
134     Channel channel();
135 
136     /**
137      * The {@link EventExecutor} that is used to dispatch the events. This can also be used to directly
138      * submit tasks that get executed in the event loop. For more information please refer to the
139      * {@link EventExecutor} javadoc.
140      */
141     EventExecutor executor();
142 
143     /**
144      * The unique name of the {@link ChannelHandlerContext}.The name was used when then {@link ChannelHandler}
145      * was added to the {@link ChannelPipeline}. This name can also be used to access the registered
146      * {@link ChannelHandler} from the {@link ChannelPipeline}.
147      */
148     String name();
149 
150     /**
151      * The {@link ChannelHandler} that is bound this {@link ChannelHandlerContext}.
152      */
153     ChannelHandler handler();
154 
155     /**
156      * Return {@code true} if the {@link ChannelHandler} which belongs to this context was removed
157      * from the {@link ChannelPipeline}. Note that this method is only meant to be called from with in the
158      * {@link EventLoop}.
159      */
160     boolean isRemoved();
161 
162     /**
163      * A {@link Channel} was registered to its {@link EventLoop}.
164      *
165      * This will result in having the  {@link ChannelInboundHandler#channelRegistered(ChannelHandlerContext)} method
166      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
167      * {@link Channel}.
168      */
169     ChannelHandlerContext fireChannelRegistered();
170 
171     /**
172      * A {@link Channel} was unregistered from its {@link EventLoop}.
173      *
174      * This will result in having the  {@link ChannelInboundHandler#channelUnregistered(ChannelHandlerContext)} method
175      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
176      * {@link Channel}.
177      */
178     ChannelHandlerContext fireChannelUnregistered();
179 
180     /**
181      * A {@link Channel} is active now, which means it is connected.
182      *
183      * This will result in having the  {@link ChannelInboundHandler#channelActive(ChannelHandlerContext)} method
184      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
185      * {@link Channel}.
186      */
187     ChannelHandlerContext fireChannelActive();
188 
189     /**
190      * A {@link Channel} is inactive now, which means it is closed.
191      *
192      * This will result in having the  {@link ChannelInboundHandler#channelInactive(ChannelHandlerContext)} method
193      * called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
194      * {@link Channel}.
195      */
196     ChannelHandlerContext fireChannelInactive();
197 
198     /**
199      * A {@link Channel} received an {@link Throwable} in one of its inbound operations.
200      *
201      * This will result in having the  {@link ChannelInboundHandler#exceptionCaught(ChannelHandlerContext, Throwable)}
202      * method  called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
203      * {@link Channel}.
204      */
205     ChannelHandlerContext fireExceptionCaught(Throwable cause);
206 
207     /**
208      * A {@link Channel} received an user defined event.
209      *
210      * This will result in having the  {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)}
211      * method  called of the next  {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
212      * {@link Channel}.
213      */
214     ChannelHandlerContext fireUserEventTriggered(Object evt);
215 
216     /**
217      * A {@link Channel} received a message.
218      *
219      * This will result in having the {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)}
220      * method  called of the next {@link ChannelInboundHandler} contained in the  {@link ChannelPipeline} of the
221      * {@link Channel}.
222      */
223     ChannelHandlerContext fireChannelRead(Object msg);
224 
225     /**
226      * Triggers an {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext)}
227      * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
228      */
229     ChannelHandlerContext fireChannelReadComplete();
230 
231     /**
232      * Triggers an {@link ChannelInboundHandler#channelWritabilityChanged(ChannelHandlerContext)}
233      * event to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
234      */
235     ChannelHandlerContext fireChannelWritabilityChanged();
236 
237     /**
238      * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
239      * completes, either because the operation was successful or because of an error.
240      * <p>
241      * This will result in having the
242      * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method
243      * called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
244      * {@link Channel}.
245      */
246     ChannelFuture bind(SocketAddress localAddress);
247 
248     /**
249      * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
250      * completes, either because the operation was successful or because of an error.
251      * <p>
252      * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with
253      * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException}
254      * will be used.
255      * <p>
256      * This will result in having the
257      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
258      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
259      * {@link Channel}.
260      */
261     ChannelFuture connect(SocketAddress remoteAddress);
262 
263     /**
264      * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the
265      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
266      * an error.
267      * <p>
268      * This will result in having the
269      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
270      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
271      * {@link Channel}.
272      */
273     ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress);
274 
275     /**
276      * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes,
277      * either because the operation was successful or because of an error.
278      * <p>
279      * This will result in having the
280      * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)}
281      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
282      * {@link Channel}.
283      */
284     ChannelFuture disconnect();
285 
286     /**
287      * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes,
288      * either because the operation was successful or because of
289      * an error.
290      *
291      * After it is closed it is not possible to reuse it again.
292      * <p>
293      * This will result in having the
294      * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)}
295      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
296      * {@link Channel}.
297      */
298     ChannelFuture close();
299 
300     /**
301      * Request to deregister from the previous assigned {@link EventExecutor} and notify the
302      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
303      * an error.
304      * <p>
305      * This will result in having the
306      * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)}
307      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
308      * {@link Channel}.
309      *
310      */
311     ChannelFuture deregister();
312 
313     /**
314      * Request to bind to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
315      * completes, either because the operation was successful or because of an error.
316      *
317      * The given {@link ChannelPromise} will be notified.
318      * <p>
319      * This will result in having the
320      * {@link ChannelOutboundHandler#bind(ChannelHandlerContext, SocketAddress, ChannelPromise)} method
321      * called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
322      * {@link Channel}.
323      */
324     ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise);
325 
326     /**
327      * Request to connect to the given {@link SocketAddress} and notify the {@link ChannelFuture} once the operation
328      * completes, either because the operation was successful or because of an error.
329      *
330      * The given {@link ChannelFuture} will be notified.
331      *
332      * <p>
333      * If the connection fails because of a connection timeout, the {@link ChannelFuture} will get failed with
334      * a {@link ConnectTimeoutException}. If it fails because of connection refused a {@link ConnectException}
335      * will be used.
336      * <p>
337      * This will result in having the
338      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
339      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
340      * {@link Channel}.
341      */
342     ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise);
343 
344     /**
345      * Request to connect to the given {@link SocketAddress} while bind to the localAddress and notify the
346      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
347      * an error.
348      *
349      * The given {@link ChannelPromise} will be notified and also returned.
350      * <p>
351      * This will result in having the
352      * {@link ChannelOutboundHandler#connect(ChannelHandlerContext, SocketAddress, SocketAddress, ChannelPromise)}
353      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
354      * {@link Channel}.
355      */
356     ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise);
357 
358     /**
359      * Request to disconnect from the remote peer and notify the {@link ChannelFuture} once the operation completes,
360      * either because the operation was successful or because of an error.
361      *
362      * The given {@link ChannelPromise} will be notified.
363      * <p>
364      * This will result in having the
365      * {@link ChannelOutboundHandler#disconnect(ChannelHandlerContext, ChannelPromise)}
366      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
367      * {@link Channel}.
368      */
369     ChannelFuture disconnect(ChannelPromise promise);
370 
371     /**
372      * Request to close the {@link Channel} and notify the {@link ChannelFuture} once the operation completes,
373      * either because the operation was successful or because of
374      * an error.
375      *
376      * After it is closed it is not possible to reuse it again.
377      * The given {@link ChannelPromise} will be notified.
378      * <p>
379      * This will result in having the
380      * {@link ChannelOutboundHandler#close(ChannelHandlerContext, ChannelPromise)}
381      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
382      * {@link Channel}.
383      */
384     ChannelFuture close(ChannelPromise promise);
385 
386     /**
387      * Request to deregister from the previous assigned {@link EventExecutor} and notify the
388      * {@link ChannelFuture} once the operation completes, either because the operation was successful or because of
389      * an error.
390      *
391      * The given {@link ChannelPromise} will be notified.
392      * <p>
393      * This will result in having the
394      * {@link ChannelOutboundHandler#deregister(ChannelHandlerContext, ChannelPromise)}
395      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
396      * {@link Channel}.
397      */
398     ChannelFuture deregister(ChannelPromise promise);
399 
400     /**
401      * Request to Read data from the {@link Channel} into the first inbound buffer, triggers an
402      * {@link ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)} event if data was
403      * read, and triggers a
404      * {@link ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete} event so the
405      * handler can decide to continue reading.  If there's a pending read operation already, this method does nothing.
406      * <p>
407      * This will result in having the
408      * {@link ChannelOutboundHandler#read(ChannelHandlerContext)}
409      * method called of the next {@link ChannelOutboundHandler} contained in the  {@link ChannelPipeline} of the
410      * {@link Channel}.
411      */
412     ChannelHandlerContext read();
413 
414     /**
415      * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}.
416      * This method will not request to actual flush, so be sure to call {@link #flush()}
417      * once you want to request to flush all pending data to the actual transport.
418      */
419     ChannelFuture write(Object msg);
420 
421     /**
422      * Request to write a message via this {@link ChannelHandlerContext} through the {@link ChannelPipeline}.
423      * This method will not request to actual flush, so be sure to call {@link #flush()}
424      * once you want to request to flush all pending data to the actual transport.
425      */
426     ChannelFuture write(Object msg, ChannelPromise promise);
427 
428     /**
429      * Request to flush all pending messages via this ChannelOutboundInvoker.
430      */
431     ChannelHandlerContext flush();
432 
433     /**
434      * Shortcut for call {@link #write(Object, ChannelPromise)} and {@link #flush()}.
435      */
436     ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);
437 
438     /**
439      * Shortcut for call {@link #write(Object)} and {@link #flush()}.
440      */
441     ChannelFuture writeAndFlush(Object msg);
442 
443     /**
444      * Return the assigned {@link ChannelPipeline}
445      */
446     ChannelPipeline pipeline();
447 
448     /**
449      * Return the assigned {@link ByteBufAllocator} which will be used to allocate {@link ByteBuf}s.
450      */
451     ByteBufAllocator alloc();
452 
453     /**
454      * Return a new {@link ChannelPromise}.
455      */
456     ChannelPromise newPromise();
457 
458     /**
459      * Return an new {@link ChannelProgressivePromise}
460      */
461     ChannelProgressivePromise newProgressivePromise();
462 
463     /**
464      * Create a new {@link ChannelFuture} which is marked as succeeded already. So {@link ChannelFuture#isSuccess()}
465      * will return {@code true}. All {@link FutureListener} added to it will be notified directly. Also
466      * every call of blocking methods will just return without blocking.
467      */
468     ChannelFuture newSucceededFuture();
469 
470     /**
471      * Create a new {@link ChannelFuture} which is marked as failed already. So {@link ChannelFuture#isSuccess()}
472      * will return {@code false}. All {@link FutureListener} added to it will be notified directly. Also
473      * every call of blocking methods will just return without blocking.
474      */
475     ChannelFuture newFailedFuture(Throwable cause);
476 
477     /**
478      * Return a special ChannelPromise which can be reused for different operations.
479      * <p>
480      * It's only supported to use
481      * it for {@link ChannelHandlerContext#write(Object, ChannelPromise)}.
482      * </p>
483      * <p>
484      * Be aware that the returned {@link ChannelPromise} will not support most operations and should only be used
485      * if you want to save an object allocation for every write operation. You will not be able to detect if the
486      * operation  was complete, only if it failed as the implementation will call
487      * {@link ChannelPipeline#fireExceptionCaught(Throwable)} in this case.
488      * </p>
489      * <strong>Be aware this is an expert feature and should be used with care!</strong>
490      */
491     ChannelPromise voidPromise();
492 
493 }