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 * https://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.util.concurrent.EventExecutorGroup;
20
21 import java.net.SocketAddress;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.SocketChannel;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.NoSuchElementException;
28
29
30 /**
31 * A list of {@link ChannelHandler}s which handles or intercepts inbound events and outbound operations of a
32 * {@link Channel}. {@link ChannelPipeline} implements an advanced form of the
33 * <a href="https://www.oracle.com/technetwork/java/interceptingfilter-142169.html">Intercepting Filter</a> pattern
34 * to give a user full control over how an event is handled and how the {@link ChannelHandler}s in a pipeline
35 * interact with each other.
36 *
37 * <h3>Creation of a pipeline</h3>
38 *
39 * Each channel has its own pipeline and it is created automatically when a new channel is created.
40 *
41 * <h3>How an event flows in a pipeline</h3>
42 *
43 * The following diagram describes how I/O events are processed by {@link ChannelHandler}s in a {@link ChannelPipeline}
44 * typically. An I/O event is handled by either a {@link ChannelInboundHandler} or a {@link ChannelOutboundHandler}
45 * and be forwarded to its closest handler by calling the event propagation methods defined in
46 * {@link ChannelHandlerContext}, such as {@link ChannelHandlerContext#fireChannelRead(Object)} and
47 * {@link ChannelHandlerContext#write(Object)}.
48 *
49 * <pre>
50 * I/O Request
51 * via {@link Channel} or
52 * {@link ChannelHandlerContext}
53 * |
54 * +---------------------------------------------------+---------------+
55 * | ChannelPipeline | |
56 * | \|/ |
57 * | +---------------------+ +-----------+----------+ |
58 * | | Inbound Handler N | | Outbound Handler 1 | |
59 * | +----------+----------+ +-----------+----------+ |
60 * | /|\ | |
61 * | | \|/ |
62 * | +----------+----------+ +-----------+----------+ |
63 * | | Inbound Handler N-1 | | Outbound Handler 2 | |
64 * | +----------+----------+ +-----------+----------+ |
65 * | /|\ . |
66 * | . . |
67 * | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
68 * | [ method call] [method call] |
69 * | . . |
70 * | . \|/ |
71 * | +----------+----------+ +-----------+----------+ |
72 * | | Inbound Handler 2 | | Outbound Handler M-1 | |
73 * | +----------+----------+ +-----------+----------+ |
74 * | /|\ | |
75 * | | \|/ |
76 * | +----------+----------+ +-----------+----------+ |
77 * | | Inbound Handler 1 | | Outbound Handler M | |
78 * | +----------+----------+ +-----------+----------+ |
79 * | /|\ | |
80 * +---------------+-----------------------------------+---------------+
81 * | \|/
82 * +---------------+-----------------------------------+---------------+
83 * | | | |
84 * | [ Socket.read() ] [ Socket.write() ] |
85 * | |
86 * | Netty Internal I/O Threads (Transport Implementation) |
87 * +-------------------------------------------------------------------+
88 * </pre>
89 * An inbound event is handled by the inbound handlers in the bottom-up direction as shown on the left side of the
90 * diagram. An inbound handler usually handles the inbound data generated by the I/O thread on the bottom of the
91 * diagram. The inbound data is often read from a remote peer via the actual input operation such as
92 * {@link SocketChannel#read(ByteBuffer)}. If an inbound event goes beyond the top inbound handler, it is discarded
93 * silently, or logged if it needs your attention.
94 * <p>
95 * An outbound event is handled by the outbound handler in the top-down direction as shown on the right side of the
96 * diagram. An outbound handler usually generates or transforms the outbound traffic such as write requests.
97 * If an outbound event goes beyond the bottom outbound handler, it is handled by an I/O thread associated with the
98 * {@link Channel}. The I/O thread often performs the actual output operation such as
99 * {@link SocketChannel#write(ByteBuffer)}.
100 * <p>
101 * For example, let us assume that we created the following pipeline:
102 * <pre>
103 * {@link ChannelPipeline} p = ...;
104 * p.addLast("1", new InboundHandlerA());
105 * p.addLast("2", new InboundHandlerB());
106 * p.addLast("3", new OutboundHandlerA());
107 * p.addLast("4", new OutboundHandlerB());
108 * p.addLast("5", new InboundOutboundHandlerX());
109 * </pre>
110 * In the example above, the class whose name starts with {@code Inbound} means it is an inbound handler.
111 * The class whose name starts with {@code Outbound} means it is a outbound handler.
112 * <p>
113 * In the given example configuration, the handler evaluation order is 1, 2, 3, 4, 5 when an event goes inbound.
114 * When an event goes outbound, the order is 5, 4, 3, 2, 1. On top of this principle, {@link ChannelPipeline} skips
115 * the evaluation of certain handlers to shorten the stack depth:
116 * <ul>
117 * <li>3 and 4 don't implement {@link ChannelInboundHandler}, and therefore the actual evaluation order of an inbound
118 * event will be: 1, 2, and 5.</li>
119 * <li>1 and 2 don't implement {@link ChannelOutboundHandler}, and therefore the actual evaluation order of a
120 * outbound event will be: 5, 4, and 3.</li>
121 * <li>If 5 implements both {@link ChannelInboundHandler} and {@link ChannelOutboundHandler}, the evaluation order of
122 * an inbound and a outbound event could be 125 and 543 respectively.</li>
123 * </ul>
124 *
125 * <h3>Forwarding an event to the next handler</h3>
126 *
127 * As you might noticed in the diagram shows, a handler has to invoke the event propagation methods in
128 * {@link ChannelHandlerContext} to forward an event to its next handler. Those methods include:
129 * <ul>
130 * <li>Inbound event propagation methods:
131 * <ul>
132 * <li>{@link ChannelHandlerContext#fireChannelRegistered()}</li>
133 * <li>{@link ChannelHandlerContext#fireChannelActive()}</li>
134 * <li>{@link ChannelHandlerContext#fireChannelRead(Object)}</li>
135 * <li>{@link ChannelHandlerContext#fireChannelReadComplete()}</li>
136 * <li>{@link ChannelHandlerContext#fireExceptionCaught(Throwable)}</li>
137 * <li>{@link ChannelHandlerContext#fireUserEventTriggered(Object)}</li>
138 * <li>{@link ChannelHandlerContext#fireChannelWritabilityChanged()}</li>
139 * <li>{@link ChannelHandlerContext#fireChannelInactive()}</li>
140 * <li>{@link ChannelHandlerContext#fireChannelUnregistered()}</li>
141 * </ul>
142 * </li>
143 * <li>Outbound event propagation methods:
144 * <ul>
145 * <li>{@link ChannelHandlerContext#bind(SocketAddress, ChannelPromise)}</li>
146 * <li>{@link ChannelHandlerContext#connect(SocketAddress, SocketAddress, ChannelPromise)}</li>
147 * <li>{@link ChannelHandlerContext#write(Object, ChannelPromise)}</li>
148 * <li>{@link ChannelHandlerContext#flush()}</li>
149 * <li>{@link ChannelHandlerContext#read()}</li>
150 * <li>{@link ChannelHandlerContext#disconnect(ChannelPromise)}</li>
151 * <li>{@link ChannelHandlerContext#close(ChannelPromise)}</li>
152 * <li>{@link ChannelHandlerContext#deregister(ChannelPromise)}</li>
153 * </ul>
154 * </li>
155 * </ul>
156 *
157 * and the following example shows how the event propagation is usually done:
158 *
159 * <pre>
160 * public class MyInboundHandler extends {@link ChannelInboundHandlerAdapter} {
161 * {@code @Override}
162 * public void channelActive({@link ChannelHandlerContext} ctx) {
163 * System.out.println("Connected!");
164 * ctx.fireChannelActive();
165 * }
166 * }
167 *
168 * public class MyOutboundHandler extends {@link ChannelOutboundHandlerAdapter} {
169 * {@code @Override}
170 * public void close({@link ChannelHandlerContext} ctx, {@link ChannelPromise} promise) {
171 * System.out.println("Closing ..");
172 * ctx.close(promise);
173 * }
174 * }
175 * </pre>
176 *
177 * <h3>Building a pipeline</h3>
178 * <p>
179 * A user is supposed to have one or more {@link ChannelHandler}s in a pipeline to receive I/O events (e.g. read) and
180 * to request I/O operations (e.g. write and close). For example, a typical server will have the following handlers
181 * in each channel's pipeline, but your mileage may vary depending on the complexity and characteristics of the
182 * protocol and business logic:
183 *
184 * <ol>
185 * <li>Protocol Decoder - translates binary data (e.g. {@link ByteBuf}) into a Java object.</li>
186 * <li>Protocol Encoder - translates a Java object into binary data.</li>
187 * <li>Business Logic Handler - performs the actual business logic.</li>
188 * </ol>
189 *
190 * and it could be represented as shown in the following example:
191 *
192 * <pre>
193 * ...
194 *
195 * {@link ChannelPipeline} pipeline = ch.pipeline();
196 *
197 * pipeline.addLast("decoder", new MyProtocolDecoder());
198 * pipeline.addLast("encoder", new MyProtocolEncoder());
199 * pipeline.addLast("handler", new MyBusinessLogicHandler());
200 * </pre>
201 *
202 * <h3>Thread safety</h3>
203 * <p>
204 * A {@link ChannelHandler} can be added or removed at any time because a {@link ChannelPipeline} is thread safe.
205 * For example, you can insert an encryption handler when sensitive information is about to be exchanged, and remove it
206 * after the exchange.
207 */
208 public interface ChannelPipeline
209 extends ChannelInboundInvoker, ChannelOutboundInvoker, Iterable<Entry<String, ChannelHandler>> {
210
211 /**
212 * Inserts a {@link ChannelHandler} at the first position of this pipeline.
213 *
214 * @param name the name of the handler to insert first
215 * @param handler the handler to insert first
216 *
217 * @throws IllegalArgumentException
218 * if there's an entry with the same name already in the pipeline
219 * @throws NullPointerException
220 * if the specified handler is {@code null}
221 */
222 ChannelPipeline addFirst(String name, ChannelHandler handler);
223
224 /**
225 * Inserts a {@link ChannelHandler} at the first position of this pipeline.
226 *
227 * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
228 * methods
229 * @param name the name of the handler to insert first
230 * @param handler the handler to insert first
231 *
232 * @throws IllegalArgumentException
233 * if there's an entry with the same name already in the pipeline
234 * @throws NullPointerException
235 * if the specified handler is {@code null}
236 * @deprecated use {@link #addFirst(String, ChannelHandler)}
237 */
238 @Deprecated
239 ChannelPipeline addFirst(EventExecutorGroup group, String name, ChannelHandler handler);
240
241 /**
242 * Appends a {@link ChannelHandler} at the last position of this pipeline.
243 *
244 * @param name the name of the handler to append
245 * @param handler the handler to append
246 *
247 * @throws IllegalArgumentException
248 * if there's an entry with the same name already in the pipeline
249 * @throws NullPointerException
250 * if the specified handler is {@code null}
251 */
252 ChannelPipeline addLast(String name, ChannelHandler handler);
253
254 /**
255 * Appends a {@link ChannelHandler} at the last position of this pipeline.
256 *
257 * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
258 * methods
259 * @param name the name of the handler to append
260 * @param handler the handler to append
261 *
262 * @throws IllegalArgumentException
263 * if there's an entry with the same name already in the pipeline
264 * @throws NullPointerException
265 * if the specified handler is {@code null}
266 * @deprecated use {@link #addLast(String, ChannelHandler)}
267 */
268 @Deprecated
269 ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);
270
271 /**
272 * Inserts a {@link ChannelHandler} before an existing handler of this
273 * pipeline.
274 *
275 * @param baseName the name of the existing handler
276 * @param name the name of the handler to insert before
277 * @param handler the handler to insert before
278 *
279 * @throws NoSuchElementException
280 * if there's no such entry with the specified {@code baseName}
281 * @throws IllegalArgumentException
282 * if there's an entry with the same name already in the pipeline
283 * @throws NullPointerException
284 * if the specified baseName or handler is {@code null}
285 */
286 ChannelPipeline addBefore(String baseName, String name, ChannelHandler handler);
287
288 /**
289 * Inserts a {@link ChannelHandler} before an existing handler of this
290 * pipeline.
291 *
292 * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
293 * methods
294 * @param baseName the name of the existing handler
295 * @param name the name of the handler to insert before
296 * @param handler the handler to insert before
297 *
298 * @throws NoSuchElementException
299 * if there's no such entry with the specified {@code baseName}
300 * @throws IllegalArgumentException
301 * if there's an entry with the same name already in the pipeline
302 * @throws NullPointerException
303 * if the specified baseName or handler is {@code null}
304 * @deprecated use {@link #addBefore(String, String, ChannelHandler)}
305 */
306 @Deprecated
307 ChannelPipeline addBefore(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);
308
309 /**
310 * Inserts a {@link ChannelHandler} after an existing handler of this
311 * pipeline.
312 *
313 * @param baseName the name of the existing handler
314 * @param name the name of the handler to insert after
315 * @param handler the handler to insert after
316 *
317 * @throws NoSuchElementException
318 * if there's no such entry with the specified {@code baseName}
319 * @throws IllegalArgumentException
320 * if there's an entry with the same name already in the pipeline
321 * @throws NullPointerException
322 * if the specified baseName or handler is {@code null}
323 */
324 ChannelPipeline addAfter(String baseName, String name, ChannelHandler handler);
325
326 /**
327 * Inserts a {@link ChannelHandler} after an existing handler of this
328 * pipeline.
329 *
330 * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}
331 * methods
332 * @param baseName the name of the existing handler
333 * @param name the name of the handler to insert after
334 * @param handler the handler to insert after
335 *
336 * @throws NoSuchElementException
337 * if there's no such entry with the specified {@code baseName}
338 * @throws IllegalArgumentException
339 * if there's an entry with the same name already in the pipeline
340 * @throws NullPointerException
341 * if the specified baseName or handler is {@code null}
342 * @deprecated use {@link #addAfter(String, String, ChannelHandler)}
343 */
344 @Deprecated
345 ChannelPipeline addAfter(EventExecutorGroup group, String baseName, String name, ChannelHandler handler);
346
347 /**
348 * Inserts {@link ChannelHandler}s at the first position of this pipeline.
349 *
350 * @param handlers the handlers to insert first
351 *
352 */
353 ChannelPipeline addFirst(ChannelHandler... handlers);
354
355 /**
356 * Inserts {@link ChannelHandler}s at the first position of this pipeline.
357 *
358 * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s
359 * methods.
360 * @param handlers the handlers to insert first
361 * @deprecated use {@link #addFirst(String, ChannelHandler)}
362 */
363 @Deprecated
364 ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers);
365
366 /**
367 * Inserts {@link ChannelHandler}s at the last position of this pipeline.
368 *
369 * @param handlers the handlers to insert last
370 *
371 */
372 ChannelPipeline addLast(ChannelHandler... handlers);
373
374 /**
375 * Inserts {@link ChannelHandler}s at the last position of this pipeline.
376 *
377 * @param group the {@link EventExecutorGroup} which will be used to execute the {@link ChannelHandler}s
378 * methods.
379 * @param handlers the handlers to insert last
380 * @deprecated use {@link #addLast(ChannelHandler...)}
381 */
382 @Deprecated
383 ChannelPipeline addLast(EventExecutorGroup group, ChannelHandler... handlers);
384
385 /**
386 * Removes the specified {@link ChannelHandler} from this pipeline.
387 *
388 * @param handler the {@link ChannelHandler} to remove
389 *
390 * @throws NoSuchElementException
391 * if there's no such handler in this pipeline
392 * @throws NullPointerException
393 * if the specified handler is {@code null}
394 */
395 ChannelPipeline remove(ChannelHandler handler);
396
397 /**
398 * Removes the {@link ChannelHandler} with the specified name from this pipeline.
399 *
400 * @param name the name under which the {@link ChannelHandler} was stored.
401 *
402 * @return the removed handler
403 *
404 * @throws NoSuchElementException
405 * if there's no such handler with the specified name in this pipeline
406 * @throws NullPointerException
407 * if the specified name is {@code null}
408 */
409 ChannelHandler remove(String name);
410
411 /**
412 * Removes the {@link ChannelHandler} of the specified type from this pipeline.
413 *
414 * @param <T> the type of the handler
415 * @param handlerType the type of the handler
416 *
417 * @return the removed handler
418 *
419 * @throws NoSuchElementException
420 * if there's no such handler of the specified type in this pipeline
421 * @throws NullPointerException
422 * if the specified handler type is {@code null}
423 */
424 <T extends ChannelHandler> T remove(Class<T> handlerType);
425
426 /**
427 * Removes the first {@link ChannelHandler} in this pipeline.
428 *
429 * @return the removed handler
430 *
431 * @throws NoSuchElementException
432 * if this pipeline is empty
433 */
434 ChannelHandler removeFirst();
435
436 /**
437 * Removes the last {@link ChannelHandler} in this pipeline.
438 *
439 * @return the removed handler
440 *
441 * @throws NoSuchElementException
442 * if this pipeline is empty
443 */
444 ChannelHandler removeLast();
445
446 /**
447 * Replaces the specified {@link ChannelHandler} with a new handler in this pipeline.
448 *
449 * @param oldHandler the {@link ChannelHandler} to be replaced
450 * @param newName the name under which the replacement should be added
451 * @param newHandler the {@link ChannelHandler} which is used as replacement
452 *
453 * @return itself
454
455 * @throws NoSuchElementException
456 * if the specified old handler does not exist in this pipeline
457 * @throws IllegalArgumentException
458 * if a handler with the specified new name already exists in this
459 * pipeline, except for the handler to be replaced
460 * @throws NullPointerException
461 * if the specified old handler or new handler is
462 * {@code null}
463 */
464 ChannelPipeline replace(ChannelHandler oldHandler, String newName, ChannelHandler newHandler);
465
466 /**
467 * Replaces the {@link ChannelHandler} of the specified name with a new handler in this pipeline.
468 *
469 * @param oldName the name of the {@link ChannelHandler} to be replaced
470 * @param newName the name under which the replacement should be added
471 * @param newHandler the {@link ChannelHandler} which is used as replacement
472 *
473 * @return the removed handler
474 *
475 * @throws NoSuchElementException
476 * if the handler with the specified old name does not exist in this pipeline
477 * @throws IllegalArgumentException
478 * if a handler with the specified new name already exists in this
479 * pipeline, except for the handler to be replaced
480 * @throws NullPointerException
481 * if the specified old handler or new handler is
482 * {@code null}
483 */
484 ChannelHandler replace(String oldName, String newName, ChannelHandler newHandler);
485
486 /**
487 * Replaces the {@link ChannelHandler} of the specified type with a new handler in this pipeline.
488 *
489 * @param oldHandlerType the type of the handler to be removed
490 * @param newName the name under which the replacement should be added
491 * @param newHandler the {@link ChannelHandler} which is used as replacement
492 *
493 * @return the removed handler
494 *
495 * @throws NoSuchElementException
496 * if the handler of the specified old handler type does not exist
497 * in this pipeline
498 * @throws IllegalArgumentException
499 * if a handler with the specified new name already exists in this
500 * pipeline, except for the handler to be replaced
501 * @throws NullPointerException
502 * if the specified old handler or new handler is
503 * {@code null}
504 */
505 <T extends ChannelHandler> T replace(Class<T> oldHandlerType, String newName,
506 ChannelHandler newHandler);
507
508 /**
509 * Returns the first {@link ChannelHandler} in this pipeline.
510 *
511 * @return the first handler. {@code null} if this pipeline is empty.
512 */
513 ChannelHandler first();
514
515 /**
516 * Returns the context of the first {@link ChannelHandler} in this pipeline.
517 *
518 * @return the context of the first handler. {@code null} if this pipeline is empty.
519 */
520 ChannelHandlerContext firstContext();
521
522 /**
523 * Returns the last {@link ChannelHandler} in this pipeline.
524 *
525 * @return the last handler. {@code null} if this pipeline is empty.
526 */
527 ChannelHandler last();
528
529 /**
530 * Returns the context of the last {@link ChannelHandler} in this pipeline.
531 *
532 * @return the context of the last handler. {@code null} if this pipeline is empty.
533 */
534 ChannelHandlerContext lastContext();
535
536 /**
537 * Returns the {@link ChannelHandler} with the specified name in this
538 * pipeline.
539 *
540 * @return the handler with the specified name.
541 * {@code null} if there's no such handler in this pipeline.
542 */
543 ChannelHandler get(String name);
544
545 /**
546 * Returns the {@link ChannelHandler} of the specified type in this
547 * pipeline.
548 *
549 * @return the handler of the specified handler type.
550 * {@code null} if there's no such handler in this pipeline.
551 */
552 <T extends ChannelHandler> T get(Class<T> handlerType);
553
554 /**
555 * Returns the context object of the specified {@link ChannelHandler} in
556 * this pipeline.
557 *
558 * @return the context object of the specified handler.
559 * {@code null} if there's no such handler in this pipeline.
560 */
561 ChannelHandlerContext context(ChannelHandler handler);
562
563 /**
564 * Returns the context object of the {@link ChannelHandler} with the
565 * specified name in this pipeline.
566 *
567 * @return the context object of the handler with the specified name.
568 * {@code null} if there's no such handler in this pipeline.
569 */
570 ChannelHandlerContext context(String name);
571
572 /**
573 * Returns the context object of the {@link ChannelHandler} of the
574 * specified type in this pipeline.
575 *
576 * @return the context object of the handler of the specified type.
577 * {@code null} if there's no such handler in this pipeline.
578 */
579 ChannelHandlerContext context(Class<? extends ChannelHandler> handlerType);
580
581 /**
582 * Returns the {@link Channel} that this pipeline is attached to.
583 *
584 * @return the channel. {@code null} if this pipeline is not attached yet.
585 */
586 Channel channel();
587
588 /**
589 * Returns the {@link List} of the handler names.
590 */
591 List<String> names();
592
593 /**
594 * Converts this pipeline into an ordered {@link Map} whose keys are
595 * handler names and whose values are handlers.
596 */
597 Map<String, ChannelHandler> toMap();
598
599 @Override
600 ChannelPipeline fireChannelRegistered();
601
602 @Override
603 ChannelPipeline fireChannelUnregistered();
604
605 @Override
606 ChannelPipeline fireChannelActive();
607
608 @Override
609 ChannelPipeline fireChannelInactive();
610
611 @Override
612 ChannelPipeline fireExceptionCaught(Throwable cause);
613
614 @Override
615 ChannelPipeline fireUserEventTriggered(Object event);
616
617 @Override
618 ChannelPipeline fireChannelRead(Object msg);
619
620 @Override
621 ChannelPipeline fireChannelReadComplete();
622
623 @Override
624 ChannelPipeline fireChannelWritabilityChanged();
625
626 @Override
627 ChannelPipeline flush();
628
629 @Override
630 default ChannelPromise newPromise() {
631 return new DefaultChannelPromise(channel());
632 }
633
634 @Override
635 default ChannelProgressivePromise newProgressivePromise() {
636 return new DefaultChannelProgressivePromise(channel());
637 }
638
639 @Override
640 default ChannelFuture newFailedFuture(Throwable cause) {
641 return new FailedChannelFuture(channel(), null, cause);
642 }
643 }