View Javadoc
1   /*
2    * Copyright 2020 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.http3;
17  
18  import io.netty.channel.ChannelHandlerContext;
19  import io.netty.channel.ChannelInboundHandlerAdapter;
20  import io.netty.channel.socket.ChannelInputShutdownEvent;
21  import io.netty.handler.codec.quic.QuicException;
22  import io.netty.handler.codec.quic.QuicStreamChannel;
23  import io.netty.util.internal.logging.InternalLogger;
24  import io.netty.util.internal.logging.InternalLoggerFactory;
25  import org.jetbrains.annotations.Nullable;
26  
27  /**
28   * {@link ChannelInboundHandlerAdapter} which makes it easy to handle
29   * <a href="https://tools.ietf.org/html/draft-ietf-quic-http-32#section-7">HTTP3 request streams</a>.
30   */
31  public abstract class Http3RequestStreamInboundHandler extends ChannelInboundHandlerAdapter {
32      private static final InternalLogger logger =
33              InternalLoggerFactory.getInstance(Http3RequestStreamInboundHandler.class);
34  
35      @Override
36      public final void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
37          if (msg instanceof Http3UnknownFrame) {
38              channelRead(ctx, (Http3UnknownFrame) msg);
39          } else if (msg instanceof Http3HeadersFrame) {
40              channelRead(ctx, (Http3HeadersFrame) msg);
41          } else if (msg instanceof Http3DataFrame) {
42              channelRead(ctx, (Http3DataFrame) msg);
43          } else {
44              super.channelRead(ctx, msg);
45          }
46      }
47  
48      @Override
49      public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
50          if (evt == ChannelInputShutdownEvent.INSTANCE) {
51              channelInputClosed(ctx);
52          }
53          ctx.fireUserEventTriggered(evt);
54      }
55  
56      @Override
57      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
58          if (cause instanceof QuicException) {
59              handleQuicException(ctx, (QuicException) cause);
60          } else if (cause instanceof Http3Exception) {
61              handleHttp3Exception(ctx, (Http3Exception) cause);
62          } else {
63              ctx.fireExceptionCaught(cause);
64          }
65      }
66  
67      /**
68       * Called once a {@link Http3HeadersFrame} is ready for this stream to process.
69       *
70       * @param ctx           the {@link ChannelHandlerContext} of this handler.
71       * @param frame         the {@link Http3HeadersFrame} that was read
72       * @throws Exception    thrown if an error happens during processing.
73       */
74      protected abstract void channelRead(ChannelHandlerContext ctx, Http3HeadersFrame frame) throws Exception;
75  
76      /**
77       * Called once a {@link Http3DataFrame} is ready for this stream to process.
78       *
79       * @param ctx           the {@link ChannelHandlerContext} of this handler.
80       * @param frame         the {@link Http3DataFrame} that was read
81       * @throws Exception    thrown if an error happens during processing.
82       */
83      protected abstract void channelRead(ChannelHandlerContext ctx, Http3DataFrame frame) throws Exception;
84  
85      /**
86       * Called once the input is closed and so no more inbound data is received on it.
87       *
88       * @param ctx           the {@link ChannelHandlerContext} of this handler.
89       * @throws Exception    thrown if an error happens during processing.
90       */
91      protected abstract void channelInputClosed(ChannelHandlerContext ctx) throws Exception;
92  
93      /**
94       * Called once a {@link Http3UnknownFrame} is ready for this stream to process. By default these frames are just
95       * released and so dropped on the floor as stated in the RFC. That said you may want to override this method if
96       * you use some custom frames which are not part of the main spec.
97       *
98       * @param ctx           the {@link ChannelHandlerContext} of this handler.
99       * @param frame         the {@link Http3UnknownFrame} that was read
100      */
101     protected void channelRead(@SuppressWarnings("unused") ChannelHandlerContext ctx, Http3UnknownFrame frame) {
102         frame.release();
103     }
104 
105     /**
106      * Called once a {@link QuicException} should be handled.
107      *
108      * @param ctx           the {@link ChannelHandlerContext} of this handler.
109      * @param exception     the {@link QuicException} that caused the error.
110      */
111     protected void handleQuicException(@SuppressWarnings("unused") ChannelHandlerContext ctx, QuicException exception) {
112         logger.debug("Caught QuicException on channel {}", ctx.channel(), exception);
113     }
114 
115     /**
116      * Called once a {@link Http3Exception} should be handled.
117      *
118      * @param ctx           the {@link ChannelHandlerContext} of this handler.
119      * @param exception     the {@link Http3Exception} that caused the error.
120      */
121     protected void handleHttp3Exception(@SuppressWarnings("unused") ChannelHandlerContext ctx,
122                                         Http3Exception exception) {
123         logger.error("Caught Http3Exception on channel {}", ctx.channel(), exception);
124     }
125 
126     /**
127      * Return the local control stream for this HTTP/3 connection. This can be used to send
128      * {@link Http3ControlStreamFrame}s to the remote peer.
129      *
130      * @param ctx           the {@link ChannelHandlerContext} of this handler.
131      * @return              the control stream.
132      */
133     @Nullable
134     protected final QuicStreamChannel controlStream(ChannelHandlerContext ctx) {
135         return Http3.getLocalControlStream(ctx.channel().parent());
136     }
137 }