View Javadoc
1   /*
2    * Copyright 2021 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.socket.ChannelInputShutdownReadComplete;
20  
21  import static io.netty.handler.codec.http3.Http3RequestStreamValidationUtils.INVALID_FRAME_READ;
22  import static io.netty.handler.codec.http3.Http3RequestStreamValidationUtils.sendStreamAbandonedIfRequired;
23  import static io.netty.handler.codec.http3.Http3RequestStreamValidationUtils.validateDataFrameRead;
24  import static io.netty.handler.codec.http3.Http3RequestStreamValidationUtils.validateHeaderFrameRead;
25  import static io.netty.handler.codec.http3.Http3RequestStreamValidationUtils.validateOnStreamClosure;
26  
27  final class Http3PushStreamClientValidationHandler
28          extends Http3FrameTypeInboundValidationHandler<Http3RequestStreamFrame> {
29      private final QpackAttributes qpackAttributes;
30      private final QpackDecoder qpackDecoder;
31      private final Http3RequestStreamCodecState decodeState;
32  
33      private long expectedLength = -1;
34      private long seenLength;
35  
36      Http3PushStreamClientValidationHandler(QpackAttributes qpackAttributes, QpackDecoder qpackDecoder,
37                                             Http3RequestStreamCodecState decodeState) {
38          super(Http3RequestStreamFrame.class);
39          this.qpackAttributes = qpackAttributes;
40          this.qpackDecoder = qpackDecoder;
41          this.decodeState = decodeState;
42      }
43  
44      @Override
45      void channelRead(ChannelHandlerContext ctx, Http3RequestStreamFrame frame) {
46          if (frame instanceof Http3PushPromiseFrame) {
47              ctx.fireChannelRead(frame);
48              return;
49          }
50  
51          if (frame instanceof Http3HeadersFrame) {
52              Http3HeadersFrame headersFrame = (Http3HeadersFrame) frame;
53              long maybeContentLength = validateHeaderFrameRead(headersFrame, ctx, decodeState);
54              if (maybeContentLength >= 0) {
55                  expectedLength = maybeContentLength;
56              } else if (maybeContentLength == INVALID_FRAME_READ) {
57                  return;
58              }
59          }
60  
61          if (frame instanceof Http3DataFrame) {
62              final Http3DataFrame dataFrame = (Http3DataFrame) frame;
63              long maybeContentLength = validateDataFrameRead(dataFrame, ctx, expectedLength, seenLength, false);
64              if (maybeContentLength >= 0) {
65                  seenLength = maybeContentLength;
66              } else if (maybeContentLength == INVALID_FRAME_READ) {
67                  return;
68              }
69          }
70          ctx.fireChannelRead(frame);
71      }
72  
73      @Override
74      public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
75          if (evt == ChannelInputShutdownReadComplete.INSTANCE) {
76              sendStreamAbandonedIfRequired(ctx, qpackAttributes, qpackDecoder, decodeState);
77              if (!validateOnStreamClosure(ctx, expectedLength, seenLength, false)) {
78                  return;
79              }
80          }
81          ctx.fireUserEventTriggered(evt);
82      }
83  
84      @Override
85      public boolean isSharable() {
86          // This handle keeps state so we can't share it.
87          return false;
88      }
89  }