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 }