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