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