View Javadoc
1   /*
2    * Copyright 2019 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.handler.codec.http2;
17  
18  import io.netty.buffer.ByteBufAllocator;
19  import io.netty.channel.Channel;
20  import io.netty.channel.ChannelConfig;
21  import io.netty.channel.ChannelFuture;
22  import io.netty.channel.ChannelFutureListener;
23  import io.netty.channel.ChannelHandler;
24  import io.netty.channel.ChannelHandlerContext;
25  import io.netty.channel.ChannelId;
26  import io.netty.channel.ChannelMetadata;
27  import io.netty.channel.ChannelOption;
28  import io.netty.channel.ChannelOutboundBuffer;
29  import io.netty.channel.ChannelPipeline;
30  import io.netty.channel.ChannelProgressivePromise;
31  import io.netty.channel.ChannelPromise;
32  import io.netty.channel.DefaultChannelConfig;
33  import io.netty.channel.DefaultChannelPipeline;
34  import io.netty.channel.EventLoop;
35  import io.netty.channel.MessageSizeEstimator;
36  import io.netty.channel.RecvByteBufAllocator;
37  import io.netty.channel.VoidChannelPromise;
38  import io.netty.channel.WriteBufferWaterMark;
39  import io.netty.channel.socket.ChannelInputShutdownReadComplete;
40  import io.netty.channel.socket.ChannelOutputShutdownEvent;
41  import io.netty.handler.codec.http2.Http2FrameCodec.DefaultHttp2FrameStream;
42  import io.netty.handler.ssl.SslCloseCompletionEvent;
43  import io.netty.util.DefaultAttributeMap;
44  import io.netty.util.ReferenceCountUtil;
45  import io.netty.util.internal.ObjectUtil;
46  import io.netty.util.internal.StringUtil;
47  import io.netty.util.internal.logging.InternalLogger;
48  import io.netty.util.internal.logging.InternalLoggerFactory;
49  
50  import java.io.IOException;
51  import java.net.SocketAddress;
52  import java.nio.channels.ClosedChannelException;
53  import java.util.ArrayDeque;
54  import java.util.Map;
55  import java.util.Queue;
56  import java.util.concurrent.RejectedExecutionException;
57  import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
58  import java.util.concurrent.atomic.AtomicLongFieldUpdater;
59  
60  import static io.netty.handler.codec.http2.Http2CodecUtil.isStreamIdValid;
61  import static io.netty.util.internal.ObjectUtil.checkNotNull;
62  import static java.lang.Math.min;
63  
64  abstract class AbstractHttp2StreamChannel extends DefaultAttributeMap implements Http2StreamChannel {
65  
66      static final Http2FrameStreamVisitor WRITABLE_VISITOR = new Http2FrameStreamVisitor() {
67          @Override
68          public boolean visit(Http2FrameStream stream) {
69              final AbstractHttp2StreamChannel childChannel = (AbstractHttp2StreamChannel)
70                      ((DefaultHttp2FrameStream) stream).attachment;
71              childChannel.trySetWritable();
72              return true;
73          }
74      };
75  
76      static final Http2FrameStreamVisitor CHANNEL_INPUT_SHUTDOWN_READ_COMPLETE_VISITOR =
77              new UserEventStreamVisitor(ChannelInputShutdownReadComplete.INSTANCE);
78  
79      static final Http2FrameStreamVisitor CHANNEL_OUTPUT_SHUTDOWN_EVENT_VISITOR =
80              new UserEventStreamVisitor(ChannelOutputShutdownEvent.INSTANCE);
81  
82      static final Http2FrameStreamVisitor SSL_CLOSE_COMPLETION_EVENT_VISITOR =
83              new UserEventStreamVisitor(SslCloseCompletionEvent.SUCCESS);
84  
85      private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractHttp2StreamChannel.class);
86  
87      private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
88  
89      /**
90       * Number of bytes to consider non-payload messages. 9 is arbitrary, but also the minimum size of an HTTP/2 frame.
91       * Primarily is non-zero.
92       */
93      private static final int MIN_HTTP2_FRAME_SIZE = 9;
94  
95      /**
96       * {@link Http2FrameStreamVisitor} that fires the user event for every active stream pipeline.
97       */
98      private static final class UserEventStreamVisitor implements Http2FrameStreamVisitor {
99  
100         private final Object event;
101 
102         UserEventStreamVisitor(Object event) {
103             this.event = checkNotNull(event, "event");
104         }
105 
106         @Override
107         public boolean visit(Http2FrameStream stream) {
108             final AbstractHttp2StreamChannel childChannel = (AbstractHttp2StreamChannel)
109                     ((DefaultHttp2FrameStream) stream).attachment;
110             childChannel.pipeline().fireUserEventTriggered(event);
111             return true;
112         }
113     }
114 
115     /**
116      * Returns the flow-control size for DATA frames, and {@value MIN_HTTP2_FRAME_SIZE} for all other frames.
117      */
118     private static final class FlowControlledFrameSizeEstimator implements MessageSizeEstimator {
119 
120         static final FlowControlledFrameSizeEstimator INSTANCE = new FlowControlledFrameSizeEstimator();
121 
122         private static final Handle HANDLE_INSTANCE = new Handle() {
123             @Override
124             public int size(Object msg) {
125                 return msg instanceof Http2DataFrame ?
126                         // Guard against overflow.
127                         (int) min(Integer.MAX_VALUE, ((Http2DataFrame) msg).initialFlowControlledBytes() +
128                                 (long) MIN_HTTP2_FRAME_SIZE) : MIN_HTTP2_FRAME_SIZE;
129             }
130         };
131 
132         @Override
133         public Handle newHandle() {
134             return HANDLE_INSTANCE;
135         }
136     }
137 
138     private static final AtomicLongFieldUpdater<AbstractHttp2StreamChannel> TOTAL_PENDING_SIZE_UPDATER =
139             AtomicLongFieldUpdater.newUpdater(AbstractHttp2StreamChannel.class, "totalPendingSize");
140 
141     private static final AtomicIntegerFieldUpdater<AbstractHttp2StreamChannel> UNWRITABLE_UPDATER =
142             AtomicIntegerFieldUpdater.newUpdater(AbstractHttp2StreamChannel.class, "unwritable");
143 
144     private static void windowUpdateFrameWriteComplete(ChannelFuture future, Channel streamChannel) {
145         Throwable cause = future.cause();
146         if (cause != null) {
147             Throwable unwrappedCause;
148             // Unwrap if needed
149             if (cause instanceof Http2FrameStreamException && (unwrappedCause = cause.getCause()) != null) {
150                 cause = unwrappedCause;
151             }
152 
153             // Notify the child-channel and close it.
154             streamChannel.pipeline().fireExceptionCaught(cause);
155             streamChannel.unsafe().close(streamChannel.unsafe().voidPromise());
156         }
157     }
158 
159     private final ChannelFutureListener windowUpdateFrameWriteListener = new ChannelFutureListener() {
160         @Override
161         public void operationComplete(ChannelFuture future) {
162             windowUpdateFrameWriteComplete(future, AbstractHttp2StreamChannel.this);
163         }
164     };
165 
166     /**
167      * The current status of the read-processing for a {@link AbstractHttp2StreamChannel}.
168      */
169     private enum ReadStatus {
170         /**
171          * No read in progress and no read was requested (yet)
172          */
173         IDLE,
174 
175         /**
176          * Reading in progress
177          */
178         IN_PROGRESS,
179 
180         /**
181          * A read operation was requested.
182          */
183         REQUESTED
184     }
185 
186     private final Http2StreamChannelConfig config = new Http2StreamChannelConfig(this);
187     private final Http2ChannelUnsafe unsafe = new Http2ChannelUnsafe();
188     private final Http2StreamChannelId channelId;
189     private final ChannelPipeline pipeline;
190     private final DefaultHttp2FrameStream stream;
191     private final ChannelPromise closePromise;
192 
193     private volatile boolean registered;
194 
195     private volatile long totalPendingSize;
196     private volatile int unwritable;
197 
198     // Cached to reduce GC
199     private Runnable fireChannelWritabilityChangedTask;
200 
201     private boolean outboundClosed;
202     private int flowControlledBytes;
203 
204     /**
205      * This variable represents if a read is in progress for the current channel or was requested.
206      * Note that depending upon the {@link RecvByteBufAllocator} behavior a read may extend beyond the
207      * {@link Http2ChannelUnsafe#beginRead()} method scope. The {@link Http2ChannelUnsafe#beginRead()} loop may
208      * drain all pending data, and then if the parent channel is reading this channel may still accept frames.
209      */
210     private ReadStatus readStatus = ReadStatus.IDLE;
211 
212     private Queue<Object> inboundBuffer;
213 
214     /** {@code true} after the first HEADERS frame has been written **/
215     private boolean firstFrameWritten;
216     private boolean readCompletePending;
217 
218     AbstractHttp2StreamChannel(DefaultHttp2FrameStream stream, int id, ChannelHandler inboundHandler) {
219         this.stream = stream;
220         stream.attachment = this;
221         pipeline = new DefaultChannelPipeline(this) {
222             @Override
223             protected void incrementPendingOutboundBytes(long size) {
224                 AbstractHttp2StreamChannel.this.incrementPendingOutboundBytes(size, true);
225             }
226 
227             @Override
228             protected void decrementPendingOutboundBytes(long size) {
229                 AbstractHttp2StreamChannel.this.decrementPendingOutboundBytes(size, true);
230             }
231 
232             @Override
233             protected void onUnhandledInboundException(Throwable cause) {
234                 // Ensure we use the correct Http2Error to close the channel.
235                 if (cause instanceof Http2FrameStreamException) {
236                     closeWithError(((Http2FrameStreamException) cause).error());
237                     return;
238                 } else {
239                     Http2Exception exception = Http2CodecUtil.getEmbeddedHttp2Exception(cause);
240                     if (exception != null) {
241                         closeWithError(exception.error());
242                         return;
243                     }
244                 }
245                 super.onUnhandledInboundException(cause);
246             }
247         };
248 
249         closePromise = pipeline.newPromise();
250         channelId = new Http2StreamChannelId(parent().id(), id);
251 
252         if (inboundHandler != null) {
253             // Add the handler to the pipeline now that we are registered.
254             pipeline.addLast(inboundHandler);
255         }
256     }
257 
258     private void incrementPendingOutboundBytes(long size, boolean invokeLater) {
259         if (size == 0) {
260             return;
261         }
262 
263         long newWriteBufferSize = TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, size);
264         if (newWriteBufferSize > config().getWriteBufferHighWaterMark()) {
265             setUnwritable(invokeLater);
266         }
267     }
268 
269     private void decrementPendingOutboundBytes(long size, boolean invokeLater) {
270         if (size == 0) {
271             return;
272         }
273 
274         long newWriteBufferSize = TOTAL_PENDING_SIZE_UPDATER.addAndGet(this, -size);
275         // Once the totalPendingSize dropped below the low water-mark we can mark the child channel
276         // as writable again. Before doing so we also need to ensure the parent channel is writable to
277         // prevent excessive buffering in the parent outbound buffer. If the parent is not writable
278         // we will mark the child channel as writable once the parent becomes writable by calling
279         // trySetWritable() later.
280         if (newWriteBufferSize < config().getWriteBufferLowWaterMark() && parent().isWritable()) {
281             setWritable(invokeLater);
282         }
283     }
284 
285     final void trySetWritable() {
286         // The parent is writable again but the child channel itself may still not be writable.
287         // Lets try to set the child channel writable to match the state of the parent channel
288         // if (and only if) the totalPendingSize is smaller then the low water-mark.
289         // If this is not the case we will try again later once we drop under it.
290         if (totalPendingSize < config().getWriteBufferLowWaterMark()) {
291             setWritable(false);
292         }
293     }
294 
295     private void setWritable(boolean invokeLater) {
296         for (;;) {
297             final int oldValue = unwritable;
298             final int newValue = oldValue & ~1;
299             if (UNWRITABLE_UPDATER.compareAndSet(this, oldValue, newValue)) {
300                 if (oldValue != 0 && newValue == 0) {
301                     fireChannelWritabilityChanged(invokeLater);
302                 }
303                 break;
304             }
305         }
306     }
307 
308     private void setUnwritable(boolean invokeLater) {
309         for (;;) {
310             final int oldValue = unwritable;
311             final int newValue = oldValue | 1;
312             if (UNWRITABLE_UPDATER.compareAndSet(this, oldValue, newValue)) {
313                 if (oldValue == 0) {
314                     fireChannelWritabilityChanged(invokeLater);
315                 }
316                 break;
317             }
318         }
319     }
320 
321     private void fireChannelWritabilityChanged(boolean invokeLater) {
322         final ChannelPipeline pipeline = pipeline();
323         if (invokeLater) {
324             Runnable task = fireChannelWritabilityChangedTask;
325             if (task == null) {
326                 fireChannelWritabilityChangedTask = task = new Runnable() {
327                     @Override
328                     public void run() {
329                         pipeline.fireChannelWritabilityChanged();
330                     }
331                 };
332             }
333             eventLoop().execute(task);
334         } else {
335             pipeline.fireChannelWritabilityChanged();
336         }
337     }
338     @Override
339     public Http2FrameStream stream() {
340         return stream;
341     }
342 
343     void closeOutbound() {
344         outboundClosed = true;
345     }
346 
347     void streamClosed() {
348         unsafe.readEOS();
349         // Attempt to drain any queued data from the queue and deliver it to the application before closing this
350         // channel.
351         unsafe.doBeginRead();
352     }
353 
354     @Override
355     public ChannelMetadata metadata() {
356         return METADATA;
357     }
358 
359     @Override
360     public ChannelConfig config() {
361         return config;
362     }
363 
364     @Override
365     public boolean isOpen() {
366         return !closePromise.isDone();
367     }
368 
369     @Override
370     public boolean isActive() {
371         return isOpen();
372     }
373 
374     @Override
375     public boolean isWritable() {
376         return unwritable == 0;
377     }
378 
379     @Override
380     public ChannelId id() {
381         return channelId;
382     }
383 
384     @Override
385     public EventLoop eventLoop() {
386         return parent().eventLoop();
387     }
388 
389     @Override
390     public Channel parent() {
391         return parentContext().channel();
392     }
393 
394     @Override
395     public boolean isRegistered() {
396         return registered;
397     }
398 
399     @Override
400     public SocketAddress localAddress() {
401         return parent().localAddress();
402     }
403 
404     @Override
405     public SocketAddress remoteAddress() {
406         return parent().remoteAddress();
407     }
408 
409     @Override
410     public ChannelFuture closeFuture() {
411         return closePromise;
412     }
413 
414     @Override
415     public long bytesBeforeUnwritable() {
416         // +1 because writability doesn't change until the threshold is crossed (not equal to).
417         long bytes = config().getWriteBufferHighWaterMark() - totalPendingSize + 1;
418         // If bytes is negative we know we are not writable, but if bytes is non-negative we have to check
419         // writability. Note that totalPendingSize and isWritable() use different volatile variables that are not
420         // synchronized together. totalPendingSize will be updated before isWritable().
421         return bytes > 0 && isWritable() ? bytes : 0;
422     }
423 
424     @Override
425     public long bytesBeforeWritable() {
426         // +1 because writability doesn't change until the threshold is crossed (not equal to).
427         long bytes = totalPendingSize - config().getWriteBufferLowWaterMark() + 1;
428         // If bytes is negative we know we are writable, but if bytes is non-negative we have to check writability.
429         // Note that totalPendingSize and isWritable() use different volatile variables that are not synchronized
430         // together. totalPendingSize will be updated before isWritable().
431         return bytes <= 0 || isWritable() ? 0 : bytes;
432     }
433 
434     @Override
435     public Unsafe unsafe() {
436         return unsafe;
437     }
438 
439     @Override
440     public ChannelPipeline pipeline() {
441         return pipeline;
442     }
443 
444     @Override
445     public ByteBufAllocator alloc() {
446         return config().getAllocator();
447     }
448 
449     @Override
450     public Channel read() {
451         pipeline().read();
452         return this;
453     }
454 
455     @Override
456     public Channel flush() {
457         pipeline().flush();
458         return this;
459     }
460 
461     @Override
462     public ChannelFuture bind(SocketAddress localAddress) {
463         return pipeline().bind(localAddress);
464     }
465 
466     @Override
467     public ChannelFuture connect(SocketAddress remoteAddress) {
468         return pipeline().connect(remoteAddress);
469     }
470 
471     @Override
472     public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
473         return pipeline().connect(remoteAddress, localAddress);
474     }
475 
476     @Override
477     public ChannelFuture disconnect() {
478         return pipeline().disconnect();
479     }
480 
481     @Override
482     public ChannelFuture close() {
483         return pipeline().close();
484     }
485 
486     @Override
487     public ChannelFuture deregister() {
488         return pipeline().deregister();
489     }
490 
491     @Override
492     public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
493         return pipeline().bind(localAddress, promise);
494     }
495 
496     @Override
497     public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
498         return pipeline().connect(remoteAddress, promise);
499     }
500 
501     @Override
502     public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
503         return pipeline().connect(remoteAddress, localAddress, promise);
504     }
505 
506     @Override
507     public ChannelFuture disconnect(ChannelPromise promise) {
508         return pipeline().disconnect(promise);
509     }
510 
511     @Override
512     public ChannelFuture close(ChannelPromise promise) {
513         return pipeline().close(promise);
514     }
515 
516     @Override
517     public ChannelFuture deregister(ChannelPromise promise) {
518         return pipeline().deregister(promise);
519     }
520 
521     @Override
522     public ChannelFuture write(Object msg) {
523         return pipeline().write(msg);
524     }
525 
526     @Override
527     public ChannelFuture write(Object msg, ChannelPromise promise) {
528         return pipeline().write(msg, promise);
529     }
530 
531     @Override
532     public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
533         return pipeline().writeAndFlush(msg, promise);
534     }
535 
536     @Override
537     public ChannelFuture writeAndFlush(Object msg) {
538         return pipeline().writeAndFlush(msg);
539     }
540 
541     @Override
542     public ChannelPromise newPromise() {
543         return pipeline().newPromise();
544     }
545 
546     @Override
547     public ChannelProgressivePromise newProgressivePromise() {
548         return pipeline().newProgressivePromise();
549     }
550 
551     @Override
552     public ChannelFuture newSucceededFuture() {
553         return pipeline().newSucceededFuture();
554     }
555 
556     @Override
557     public ChannelFuture newFailedFuture(Throwable cause) {
558         return pipeline().newFailedFuture(cause);
559     }
560 
561     @Override
562     public ChannelPromise voidPromise() {
563         return pipeline().voidPromise();
564     }
565 
566     @Override
567     public int hashCode() {
568         return id().hashCode();
569     }
570 
571     @Override
572     public boolean equals(Object o) {
573         return this == o;
574     }
575 
576     @Override
577     public int compareTo(Channel o) {
578         if (this == o) {
579             return 0;
580         }
581 
582         return id().compareTo(o.id());
583     }
584 
585     @Override
586     public String toString() {
587         return parent().toString() + '/' + channelId.getSequenceId() + " (H2 - " + stream + ')';
588     }
589 
590     void fireChildExceptionCaught(Throwable cause) {
591         pipeline().fireExceptionCaught(cause);
592     }
593 
594     void fireChildUserEventTriggered(Object evt) {
595         pipeline().fireUserEventTriggered(evt);
596     }
597 
598     /**
599      * Receive a read message. This does not notify handlers unless a read is in progress on the
600      * channel.
601      */
602     void fireChildRead(Http2Frame frame) {
603         assert eventLoop().inEventLoop();
604         if (!isActive()) {
605             ReferenceCountUtil.release(frame);
606         } else if (readStatus != ReadStatus.IDLE && isInboundBufferEmpty()) {
607             // A read is in progress or has been requested and nothing is queued, so dispatch directly. If frames are
608             // still queued (e.g. this frame was delivered re-entrantly while doBeginRead() is running pipeline
609             // callbacks after it stopped early) we must queue behind them below to preserve ordering; the read loop
610             // that is still on the stack will drain them.
611             final RecvByteBufAllocator.Handle allocHandle = unsafe.recvBufAllocHandle();
612 
613             unsafe.doRead0(frame, allocHandle);
614             // We currently don't need to check for readEOS because the parent channel and child channel are limited
615             // to the same EventLoop thread. There are a limited number of frame types that may come after EOS is
616             // read (unknown, reset) and the trade off is less conditionals for the hot path (headers/data) at the
617             // cost of additional readComplete notifications on the rare path.
618             if (allocHandle.continueReading()) {
619                 maybeAddChannelToReadCompletePendingQueue();
620             } else {
621                 unsafe.notifyReadComplete(allocHandle, true, false);
622             }
623         } else {
624             if (inboundBuffer == null) {
625                 inboundBuffer = new ArrayDeque<Object>(4);
626             }
627             inboundBuffer.add(frame);
628         }
629     }
630 
631     private boolean isInboundBufferEmpty() {
632         return inboundBuffer == null || inboundBuffer.isEmpty();
633     }
634 
635     void fireChildReadComplete() {
636         assert eventLoop().inEventLoop();
637         assert readStatus != ReadStatus.IDLE || !readCompletePending;
638         unsafe.notifyReadComplete(unsafe.recvBufAllocHandle(), false, false);
639     }
640 
641     final void closeWithError(Http2Error error) {
642         assert eventLoop().inEventLoop();
643         unsafe.close(unsafe.voidPromise(), error);
644     }
645 
646     private final class Http2ChannelUnsafe implements Unsafe {
647         private final VoidChannelPromise unsafeVoidPromise =
648                 new VoidChannelPromise(AbstractHttp2StreamChannel.this, false);
649         @SuppressWarnings("deprecation")
650         private RecvByteBufAllocator.Handle recvHandle;
651         private boolean writeDoneAndNoFlush;
652         private boolean closeInitiated;
653         private boolean readEOS;
654 
655         private boolean receivedEndOfStream;
656         private boolean sentEndOfStream;
657 
658         @Override
659         public void connect(final SocketAddress remoteAddress,
660                             SocketAddress localAddress, final ChannelPromise promise) {
661             if (!promise.setUncancellable()) {
662                 return;
663             }
664             promise.setFailure(new UnsupportedOperationException());
665         }
666 
667         @Override
668         public RecvByteBufAllocator.Handle recvBufAllocHandle() {
669             if (recvHandle == null) {
670                 recvHandle = config().getRecvByteBufAllocator().newHandle();
671                 recvHandle.reset(config());
672             }
673             return recvHandle;
674         }
675 
676         @Override
677         public SocketAddress localAddress() {
678             return parent().unsafe().localAddress();
679         }
680 
681         @Override
682         public SocketAddress remoteAddress() {
683             return parent().unsafe().remoteAddress();
684         }
685 
686         @Override
687         public void register(EventLoop eventLoop, ChannelPromise promise) {
688             if (!promise.setUncancellable()) {
689                 return;
690             }
691             if (registered) {
692                 promise.setFailure(new UnsupportedOperationException("Re-register is not supported"));
693                 return;
694             }
695 
696             registered = true;
697 
698             promise.setSuccess();
699 
700             pipeline().fireChannelRegistered();
701             if (isActive()) {
702                 pipeline().fireChannelActive();
703             }
704         }
705 
706         @Override
707         public void bind(SocketAddress localAddress, ChannelPromise promise) {
708             if (!promise.setUncancellable()) {
709                 return;
710             }
711             promise.setFailure(new UnsupportedOperationException());
712         }
713 
714         @Override
715         public void disconnect(ChannelPromise promise) {
716             close(promise);
717         }
718 
719         @Override
720         public void close(final ChannelPromise promise) {
721             close(promise, null);
722         }
723 
724         private void close(final ChannelPromise promise, Http2Error error) {
725             if (!promise.setUncancellable()) {
726                 return;
727             }
728             if (closeInitiated) {
729                 if (closePromise.isDone()) {
730                     // Closed already.
731                     promise.setSuccess();
732                 } else if (!(promise instanceof VoidChannelPromise)) { // Only needed if no VoidChannelPromise.
733                     // This means close() was called before so we just register a listener and return
734                     closePromise.addListener(new ChannelFutureListener() {
735                         @Override
736                         public void operationComplete(ChannelFuture future) {
737                             promise.setSuccess();
738                         }
739                     });
740                 }
741                 return;
742             }
743             closeInitiated = true;
744             // Just set to false as removing from an underlying queue would even be more expensive.
745             readCompletePending = false;
746 
747             final boolean wasActive = isActive();
748 
749             // There is no need to update the local window as once the stream is closed all the pending bytes will be
750             // given back to the connection window by the controller itself.
751 
752             // Only ever send a reset frame if the connection is still alive and if the stream was created before
753             // as otherwise we may send a RST on a stream in an invalid state and cause a connection error.
754             if (parent().isActive() && isStreamIdValid(stream.id())) {
755                 // If error is null we know that the close was not triggered by an error and so we should only
756                 // try to send a RST frame if we didn't signal the end of the stream before.
757                 if (error == null) {
758                     if (!readEOS && !(receivedEndOfStream && sentEndOfStream)) {
759                         Http2StreamFrame resetFrame = new DefaultHttp2ResetFrame(Http2Error.CANCEL).stream(stream());
760                         write(resetFrame, unsafe().voidPromise());
761                         flush();
762                     }
763                 } else {
764                     // Close was triggered by a stream error, in this case we always want to send a RST frame.
765                     Http2StreamFrame resetFrame = new DefaultHttp2ResetFrame(error).stream(stream());
766                     write(resetFrame, unsafe().voidPromise());
767                     flush();
768                 }
769             }
770 
771             if (inboundBuffer != null) {
772                 for (;;) {
773                     Object msg = inboundBuffer.poll();
774                     if (msg == null) {
775                         break;
776                     }
777                     ReferenceCountUtil.release(msg);
778                 }
779                 inboundBuffer = null;
780             }
781 
782             // The promise should be notified before we call fireChannelInactive().
783             outboundClosed = true;
784             closePromise.setSuccess();
785             promise.setSuccess();
786 
787             fireChannelInactiveAndDeregister(voidPromise(), wasActive);
788         }
789 
790         @Override
791         public void closeForcibly() {
792             close(unsafe().voidPromise());
793         }
794 
795         @Override
796         public void deregister(ChannelPromise promise) {
797             fireChannelInactiveAndDeregister(promise, false);
798         }
799 
800         private void fireChannelInactiveAndDeregister(final ChannelPromise promise,
801                                                       final boolean fireChannelInactive) {
802             if (!promise.setUncancellable()) {
803                 return;
804             }
805 
806             if (!registered) {
807                 promise.setSuccess();
808                 return;
809             }
810 
811             // As a user may call deregister() from within any method while doing processing in the ChannelPipeline,
812             // we need to ensure we do the actual deregister operation later. This is necessary to preserve the
813             // behavior of the AbstractChannel, which always invokes channelUnregistered and channelInactive
814             // events 'later' to ensure the current events in the handler are completed before these events.
815             //
816             // See:
817             // https://github.com/netty/netty/issues/4435
818             invokeLater(promise.channel(), new Runnable() {
819                 @Override
820                 public void run() {
821                     if (fireChannelInactive) {
822                         pipeline.fireChannelInactive();
823                     }
824                     // The user can fire `deregister` events multiple times but we only want to fire the pipeline
825                     // event if the channel was actually registered.
826                     if (registered) {
827                         registered = false;
828                         pipeline.fireChannelUnregistered();
829                     }
830                     safeSetSuccess(promise);
831                 }
832             });
833         }
834 
835         private void safeSetSuccess(ChannelPromise promise) {
836             if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) {
837                 logger.warn("{} Failed to mark a promise as success because it is done already: {}",
838                         promise.channel(), promise);
839             }
840         }
841 
842         private void invokeLater(Channel channel, Runnable task) {
843             try {
844                 // This method is used by outbound operation implementations to trigger an inbound event later.
845                 // They do not trigger an inbound event immediately because an outbound operation might have been
846                 // triggered by another inbound event handler method.  If fired immediately, the call stack
847                 // will look like this for example:
848                 //
849                 //   handlerA.inboundBufferUpdated() - (1) an inbound handler method closes a connection.
850                 //   -> handlerA.ctx.close()
851                 //     -> channel.unsafe.close()
852                 //       -> handlerA.channelInactive() - (2) another inbound handler method called while in (1) yet
853                 //
854                 // which means the execution of two inbound handler methods of the same handler overlap undesirably.
855                 eventLoop().execute(task);
856             } catch (RejectedExecutionException e) {
857                 logger.warn("{} Can't invoke task later as EventLoop rejected it", channel, e);
858             }
859         }
860 
861         @Override
862         public void beginRead() {
863             if (!isActive()) {
864                 return;
865             }
866             final boolean windowUpdated = updateLocalWindowIfNeeded();
867 
868             switch (readStatus) {
869                 case IDLE:
870                     readStatus = ReadStatus.IN_PROGRESS;
871                     // doBeginRead() always flushes (or defers to the parent's read-complete flush).
872                     doBeginRead();
873                     return;
874                 case IN_PROGRESS:
875                     readStatus = ReadStatus.REQUESTED;
876                     break;
877                 default:
878                     break;
879             }
880             if (windowUpdated) {
881                 // A WINDOW_UPDATE was just written above, but no read loop runs in this branch to flush it, so an
882                 // unflushed frame here can stall the remote peer forever (netty/netty#17600).
883                 //
884                 // flush() alone is not enough: it no-ops while isParentReadInProgress(), since
885                 // Http2MultiplexHandler batches all children's flushes into one ctx.flush() at the end of its read
886                 // loop (processPendingReadCompleteQueue()) -- but that batched flush only runs if some channel
887                 // registered via maybeAddChannelToReadCompletePendingQueue(), which doBeginRead()/fireChildRead()
888                 // do but this branch doesn't. If a cross-thread setAutoRead(true) lands here as the only activity
889                 // in the parent's read loop, the queue stays empty, the end-of-loop flush is skipped, and this
890                 // WINDOW_UPDATE (flowControlledBytes already zeroed) is never retried -- permanent stall.
891                 //
892                 // So register into that queue while the parent is reading; otherwise flush immediately.
893                 if (isParentReadInProgress()) {
894                     maybeAddChannelToReadCompletePendingQueue();
895                 } else {
896                     flush();
897                 }
898             }
899         }
900 
901         private Object pollQueuedMessage() {
902             return inboundBuffer == null ? null : inboundBuffer.poll();
903         }
904 
905         void doBeginRead() {
906             if (readStatus == ReadStatus.IDLE) {
907                 // Don't wait for the user to request a read to notify of channel closure.
908                 if (readEOS && isInboundBufferEmpty()) {
909                     // Double check there is nothing left to flush such as a window update frame.
910                     flush();
911                     closeIfReadEOSAndDrained();
912                 }
913             } else {
914                 do { // Process messages until there are none left (or the user stopped requesting) and also handle EOS.
915                     Object message = pollQueuedMessage();
916                     if (message == null) {
917                         // Double check there is nothing left to flush such as a window update frame.
918                         flush();
919                         if (!isInboundBufferEmpty()) {
920                             // The flush re-entrantly delivered more frames which got queued; keep reading if we
921                             // still should.
922                             continue;
923                         }
924                         closeIfReadEOSAndDrained();
925                         break;
926                     }
927                     final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
928                     allocHandle.reset(config());
929                     boolean continueReading = false;
930                     do {
931                         doRead0((Http2Frame) message, allocHandle);
932                     } while ((readEOS || (continueReading = allocHandle.continueReading()))
933                             && (message = pollQueuedMessage()) != null);
934 
935                     if (continueReading && isParentReadInProgress() && !readEOS) {
936                         // Currently the parent and child channel are on the same EventLoop thread. If the parent is
937                         // currently reading it is possible that more frames will be delivered to this child channel. In
938                         // the case that this child channel still wants to read we delay the channelReadComplete on this
939                         // child channel until the parent is done reading.
940                         maybeAddChannelToReadCompletePendingQueue();
941                     } else {
942                         notifyReadComplete(allocHandle, true, true);
943 
944                         // While in the read loop reset the readState AFTER calling readComplete (or other pipeline
945                         // callbacks) to prevents re-entry into this method (if autoRead is disabled and the user calls
946                         // read on each readComplete) and StackOverflowException.
947                         resetReadStatus();
948                     }
949                 } while (readStatus != ReadStatus.IDLE);
950             }
951         }
952 
953         void readEOS() {
954             readEOS = true;
955         }
956 
957         private boolean updateLocalWindowIfNeeded() {
958             if (flowControlledBytes != 0 && !parentContext().isRemoved() && config.autoStreamFlowControl) {
959                 int bytes = flowControlledBytes;
960                 flowControlledBytes = 0;
961                 writeWindowUpdateFrame(new DefaultHttp2WindowUpdateFrame(bytes).stream(stream));
962                 return true;
963             }
964             return false;
965         }
966 
967         void updateLocalWindowIfNeededAndFlush() {
968             if (updateLocalWindowIfNeeded()) {
969                 flush();
970             }
971         }
972 
973         private void resetReadStatus() {
974             readStatus = readStatus == ReadStatus.REQUESTED ? ReadStatus.IN_PROGRESS : ReadStatus.IDLE;
975         }
976 
977         void notifyReadComplete(RecvByteBufAllocator.Handle allocHandle, boolean forceReadComplete,
978                                 boolean inReadLoop) {
979             if (!readCompletePending && !forceReadComplete) {
980                 return;
981             }
982             // Set to false just in case we added the channel multiple times before.
983             readCompletePending = false;
984 
985             if (!inReadLoop) {
986                 // While in the read loop we reset the state after calling pipeline methods to prevent StackOverflow.
987                 resetReadStatus();
988             }
989 
990             allocHandle.readComplete();
991             pipeline().fireChannelReadComplete();
992             // Reading data may result in frames being written (e.g. WINDOW_UPDATE, RST, etc..). If the parent
993             // channel is not currently reading we need to force a flush at the child channel, because we cannot
994             // rely upon flush occurring in channelReadComplete on the parent channel.
995             flush();
996             closeIfReadEOSAndDrained();
997         }
998 
999         private void closeIfReadEOSAndDrained() {
1000             // Pipeline callbacks and flush() can re-entrantly deliver more frames, including the one that ends the
1001             // stream, and queue them if the user stopped reading. Only close once all of them have been read,
1002             // otherwise the queued frames would be released and the stream silently truncated.
1003             if (readEOS && isInboundBufferEmpty()) {
1004                 closeForcibly();
1005             }
1006         }
1007 
1008         @SuppressWarnings("deprecation")
1009         void doRead0(Http2Frame frame, RecvByteBufAllocator.Handle allocHandle) {
1010             final int bytes;
1011             if (frame instanceof Http2DataFrame) {
1012                 bytes = ((Http2DataFrame) frame).initialFlowControlledBytes();
1013                 // It is important that we increment the flowControlledBytes before we call fireChannelRead(...)
1014                 // as it may cause a read() that will call updateLocalWindowIfNeeded() and we need to ensure
1015                 // in this case that we accounted for it.
1016                 //
1017                 // See https://github.com/netty/netty/issues/9663
1018                 flowControlledBytes += bytes;
1019             } else {
1020                 bytes = MIN_HTTP2_FRAME_SIZE;
1021             }
1022 
1023             // Let's keep track of what we received as the stream state itself will only be updated once the frame
1024             // was dispatched for reading which might cause problems if we try to close the channel in a write future.
1025             receivedEndOfStream |= isEndOfStream(frame);
1026 
1027             // Update before firing event through the pipeline to be consistent with other Channel implementation.
1028             allocHandle.attemptedBytesRead(bytes);
1029             allocHandle.lastBytesRead(bytes);
1030             allocHandle.incMessagesRead(1);
1031 
1032             pipeline().fireChannelRead(frame);
1033         }
1034 
1035         private ChannelFuture writeWindowUpdateFrame(Http2WindowUpdateFrame windowUpdateFrame) {
1036             ChannelFuture future = write0(parentContext(), windowUpdateFrame);
1037             // window update frames are commonly swallowed by the Http2FrameCodec and the promise is synchronously
1038             // completed but the flow controller _may_ have generated a wire level WINDOW_UPDATE. Therefore we need,
1039             // to assume there was a write done that needs to be flushed or we risk flow control starvation.
1040             writeDoneAndNoFlush = true;
1041             // Add a listener which will notify and teardown the stream
1042             // when a window update fails if needed or check the result of the future directly if it was completed
1043             // already.
1044             // See https://github.com/netty/netty/issues/9663
1045             if (future.isDone()) {
1046                 windowUpdateFrameWriteComplete(future, AbstractHttp2StreamChannel.this);
1047             } else {
1048                 future.addListener(windowUpdateFrameWriteListener);
1049             }
1050             return future;
1051         }
1052 
1053         @Override
1054         public void write(Object msg, final ChannelPromise promise) {
1055             // After this point its not possible to cancel a write anymore.
1056             if (!promise.setUncancellable()) {
1057                 ReferenceCountUtil.release(msg);
1058                 return;
1059             }
1060 
1061             if (!isActive() ||
1062                     // Once the outbound side was closed we should not allow header / data frames
1063                     outboundClosed && (msg instanceof Http2HeadersFrame || msg instanceof Http2DataFrame)) {
1064                 ReferenceCountUtil.release(msg);
1065                 promise.setFailure(new ClosedChannelException());
1066                 return;
1067             }
1068 
1069             try {
1070                 if (msg instanceof Http2StreamFrame) {
1071                     Http2StreamFrame frame = validateStreamFrame((Http2StreamFrame) msg).stream(stream());
1072                     if (msg instanceof Http2WindowUpdateFrame) {
1073                         Http2WindowUpdateFrame updateFrame = (Http2WindowUpdateFrame) msg;
1074                         if (config.autoStreamFlowControl) {
1075                             ReferenceCountUtil.release(msg);
1076                             promise.setFailure(new UnsupportedOperationException(
1077                                     Http2StreamChannelOption.AUTO_STREAM_FLOW_CONTROL + " is set to false"));
1078                             return;
1079                         }
1080                         try {
1081                             ObjectUtil.checkInRange(updateFrame.windowSizeIncrement(), 0,
1082                                     flowControlledBytes, "windowSizeIncrement");
1083                         } catch (RuntimeException e) {
1084                             ReferenceCountUtil.release(updateFrame);
1085                             promise.setFailure(e);
1086                             return;
1087                         }
1088                         flowControlledBytes -= updateFrame.windowSizeIncrement();
1089                         if (parentContext().isRemoved()) {
1090                             ReferenceCountUtil.release(msg);
1091                             promise.setFailure(new ClosedChannelException());
1092                             return;
1093                         }
1094                         ChannelFuture f = writeWindowUpdateFrame(updateFrame);
1095                         if (f.isDone()) {
1096                             writeComplete(f, promise);
1097                         } else {
1098                             f.addListener(new ChannelFutureListener() {
1099                                 @Override
1100                                 public void operationComplete(ChannelFuture future) {
1101                                     writeComplete(future, promise);
1102                                 }
1103                             });
1104                         }
1105                     } else {
1106                         writeHttp2StreamFrame(frame, promise);
1107                     }
1108                 } else {
1109                     String msgStr = msg.toString();
1110                     ReferenceCountUtil.release(msg);
1111                     promise.setFailure(new IllegalArgumentException(
1112                             "Message must be an " + StringUtil.simpleClassName(Http2StreamFrame.class) +
1113                                     ": " + msgStr));
1114                 }
1115             } catch (Throwable t) {
1116                 promise.tryFailure(t);
1117             }
1118         }
1119 
1120         private boolean isEndOfStream(Http2Frame frame) {
1121             if (frame instanceof Http2HeadersFrame) {
1122                 return ((Http2HeadersFrame) frame).isEndStream();
1123             }
1124             if (frame instanceof Http2DataFrame) {
1125                 return ((Http2DataFrame) frame).isEndStream();
1126             }
1127             return false;
1128         }
1129 
1130         private void writeHttp2StreamFrame(Http2StreamFrame frame, final ChannelPromise promise) {
1131             if (!firstFrameWritten && !isStreamIdValid(stream().id()) && !(frame instanceof Http2HeadersFrame)) {
1132                 ReferenceCountUtil.release(frame);
1133                 promise.setFailure(
1134                     new IllegalArgumentException("The first frame must be a headers frame. Was: "
1135                         + frame.name()));
1136                 return;
1137             }
1138 
1139             final boolean firstWrite;
1140             if (firstFrameWritten) {
1141                 firstWrite = false;
1142             } else {
1143                 firstWrite = firstFrameWritten = true;
1144             }
1145 
1146             // Let's keep track of what we send as the stream state itself will only be updated once the frame
1147             // was written which might cause problems if we try to close the channel in a write future.
1148             sentEndOfStream |= isEndOfStream(frame);
1149             ChannelFuture f = write0(parentContext(), frame);
1150             if (f.isDone()) {
1151                 if (firstWrite) {
1152                     firstWriteComplete(f, promise);
1153                 } else {
1154                     writeComplete(f, promise);
1155                 }
1156             } else {
1157                 final long bytes = FlowControlledFrameSizeEstimator.HANDLE_INSTANCE.size(frame);
1158                 incrementPendingOutboundBytes(bytes, false);
1159                 f.addListener(new ChannelFutureListener() {
1160                     @Override
1161                     public void operationComplete(ChannelFuture future) {
1162                         if (firstWrite) {
1163                             firstWriteComplete(future, promise);
1164                         } else {
1165                             writeComplete(future, promise);
1166                         }
1167                         decrementPendingOutboundBytes(bytes, false);
1168                     }
1169                 });
1170                 writeDoneAndNoFlush = true;
1171             }
1172         }
1173 
1174         private void firstWriteComplete(ChannelFuture future, ChannelPromise promise) {
1175             Throwable cause = future.cause();
1176             if (cause == null) {
1177                 promise.setSuccess();
1178             } else {
1179                 // If the first write fails there is not much we can do, just close
1180                 closeForcibly();
1181                 promise.setFailure(wrapStreamClosedError(cause));
1182             }
1183         }
1184 
1185         private void writeComplete(ChannelFuture future, ChannelPromise promise) {
1186             Throwable cause = future.cause();
1187             if (cause == null) {
1188                 promise.setSuccess();
1189             } else {
1190                 Throwable error = wrapStreamClosedError(cause);
1191                 // To make it more consistent with AbstractChannel we handle all IOExceptions here.
1192                 if (error instanceof IOException) {
1193                     if (config.isAutoClose()) {
1194                         // Close channel if needed.
1195                         closeForcibly();
1196                     } else {
1197                         // TODO: Once Http2StreamChannel extends DuplexChannel we should call shutdownOutput(...)
1198                         outboundClosed = true;
1199                     }
1200                 }
1201                 promise.setFailure(error);
1202             }
1203         }
1204 
1205         private Throwable wrapStreamClosedError(Throwable cause) {
1206             // If the error was caused by STREAM_CLOSED we should use a ClosedChannelException to better
1207             // mimic other transports and make it easier to reason about what exceptions to expect.
1208             if (cause instanceof Http2Exception && ((Http2Exception) cause).error() == Http2Error.STREAM_CLOSED) {
1209                 return new ClosedChannelException().initCause(cause);
1210             }
1211             return cause;
1212         }
1213 
1214         private Http2StreamFrame validateStreamFrame(Http2StreamFrame frame) {
1215             if (frame.stream() != null && frame.stream() != stream) {
1216                 String msgString = frame.toString();
1217                 ReferenceCountUtil.release(frame);
1218                 throw new IllegalArgumentException(
1219                         "Stream " + frame.stream() + " must not be set on the frame: " + msgString);
1220             }
1221             return frame;
1222         }
1223 
1224         @Override
1225         public void flush() {
1226             // If we are currently in the parent channel's read loop we should just ignore the flush.
1227             // We will ensure we trigger ctx.flush() after we processed all Channels later on and
1228             // so aggregate the flushes. This is done as ctx.flush() is expensive when as it may trigger an
1229             // write(...) or writev(...) operation on the socket.
1230             if (!writeDoneAndNoFlush || isParentReadInProgress()) {
1231                 // There is nothing to flush so this is a NOOP.
1232                 return;
1233             }
1234             // We need to set this to false before we call flush0(...) as ChannelFutureListener may produce more data
1235             // that are explicit flushed.
1236             writeDoneAndNoFlush = false;
1237             flush0(parentContext());
1238         }
1239 
1240         @Override
1241         public ChannelPromise voidPromise() {
1242             return unsafeVoidPromise;
1243         }
1244 
1245         @Override
1246         public ChannelOutboundBuffer outboundBuffer() {
1247             // Always return null as we not use the ChannelOutboundBuffer and not even support it.
1248             return null;
1249         }
1250     }
1251 
1252     /**
1253      * {@link ChannelConfig} so that the high and low writebuffer watermarks can reflect the outbound flow control
1254      * window, without having to create a new {@link WriteBufferWaterMark} object whenever the flow control window
1255      * changes.
1256      */
1257     private static final class Http2StreamChannelConfig extends DefaultChannelConfig {
1258 
1259         volatile boolean autoStreamFlowControl = true;
1260         Http2StreamChannelConfig(Channel channel) {
1261             super(channel);
1262         }
1263 
1264         @Override
1265         public MessageSizeEstimator getMessageSizeEstimator() {
1266             return FlowControlledFrameSizeEstimator.INSTANCE;
1267         }
1268 
1269         @Override
1270         public ChannelConfig setMessageSizeEstimator(MessageSizeEstimator estimator) {
1271             throw new UnsupportedOperationException();
1272         }
1273 
1274         @Override
1275         public ChannelConfig setRecvByteBufAllocator(RecvByteBufAllocator allocator) {
1276             if (!(allocator.newHandle() instanceof RecvByteBufAllocator.ExtendedHandle)) {
1277                 throw new IllegalArgumentException("allocator.newHandle() must return an object of type: " +
1278                         RecvByteBufAllocator.ExtendedHandle.class);
1279             }
1280             super.setRecvByteBufAllocator(allocator);
1281             return this;
1282         }
1283 
1284         @Override
1285         public Map<ChannelOption<?>, Object> getOptions() {
1286             return getOptions(
1287                     super.getOptions(),
1288                     Http2StreamChannelOption.AUTO_STREAM_FLOW_CONTROL);
1289         }
1290 
1291         @SuppressWarnings("unchecked")
1292         @Override
1293         public <T> T getOption(ChannelOption<T> option) {
1294             if (option == Http2StreamChannelOption.AUTO_STREAM_FLOW_CONTROL) {
1295                 return (T) Boolean.valueOf(autoStreamFlowControl);
1296             }
1297             return super.getOption(option);
1298         }
1299 
1300         @Override
1301         public <T> boolean setOption(ChannelOption<T> option, T value) {
1302             validate(option, value);
1303             if (option == Http2StreamChannelOption.AUTO_STREAM_FLOW_CONTROL) {
1304                 boolean newValue = (Boolean) value;
1305                 boolean changed = newValue && !autoStreamFlowControl;
1306                 autoStreamFlowControl = (Boolean) value;
1307                 if (changed) {
1308                     if (channel.isRegistered()) {
1309                         final Http2ChannelUnsafe unsafe = (Http2ChannelUnsafe) channel.unsafe();
1310                         if (channel.eventLoop().inEventLoop()) {
1311                             unsafe.updateLocalWindowIfNeededAndFlush();
1312                         } else {
1313                             channel.eventLoop().execute(new Runnable() {
1314                                 @Override
1315                                 public void run() {
1316                                     unsafe.updateLocalWindowIfNeededAndFlush();
1317                                 }
1318                             });
1319                         }
1320                     }
1321                 }
1322                 return true;
1323             }
1324             return super.setOption(option, value);
1325         }
1326     }
1327 
1328     private void maybeAddChannelToReadCompletePendingQueue() {
1329         if (!readCompletePending) {
1330             readCompletePending = true;
1331             addChannelToReadCompletePendingQueue();
1332         }
1333     }
1334 
1335     protected void flush0(ChannelHandlerContext ctx) {
1336         ctx.flush();
1337     }
1338 
1339     protected ChannelFuture write0(ChannelHandlerContext ctx, Object msg) {
1340         ChannelPromise promise = ctx.newPromise();
1341         ctx.write(msg, promise);
1342         return promise;
1343     }
1344 
1345     protected abstract boolean isParentReadInProgress();
1346     protected abstract void addChannelToReadCompletePendingQueue();
1347     protected abstract ChannelHandlerContext parentContext();
1348 }