View Javadoc
1   /*
2    * Copyright 2017 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.netty5.handler.codec.http2;
17  
18  import io.netty5.util.internal.UnstableApi;
19  
20  import static java.util.Objects.requireNonNull;
21  
22  /**
23   * Builder for the {@link Http2FrameCodec}.
24   */
25  @UnstableApi
26  public class Http2FrameCodecBuilder extends
27          AbstractHttp2ConnectionHandlerBuilder<Http2FrameCodec, Http2FrameCodecBuilder> {
28  
29      private Http2FrameWriter frameWriter;
30  
31      /**
32       * Allows overriding behavior of existing builder.
33       * <p>
34       * Users of this constructor are responsible for invoking {@link #server(boolean)} method or overriding
35       * {@link #isServer()} method to give the builder information if the {@link Http2Connection}(s) it creates are in
36       * server or client mode.
37       *
38       * @see AbstractHttp2ConnectionHandlerBuilder
39       */
40      protected Http2FrameCodecBuilder() {
41      }
42  
43      Http2FrameCodecBuilder(boolean server) {
44          server(server);
45          // For backwards compatibility we should disable to timeout by default at this layer.
46          gracefulShutdownTimeoutMillis(0);
47      }
48  
49      /**
50       * Creates a builder for an HTTP/2 client.
51       */
52      public static Http2FrameCodecBuilder forClient() {
53          return new Http2FrameCodecBuilder(false);
54      }
55  
56      /**
57       * Creates a builder for an HTTP/2 server.
58       */
59      public static Http2FrameCodecBuilder forServer() {
60          return new Http2FrameCodecBuilder(true);
61      }
62  
63      // For testing only.
64      Http2FrameCodecBuilder frameWriter(Http2FrameWriter frameWriter) {
65          this.frameWriter = requireNonNull(frameWriter, "frameWriter");
66          return this;
67      }
68  
69      @Override
70      public Http2Settings initialSettings() {
71          return super.initialSettings();
72      }
73  
74      @Override
75      public Http2FrameCodecBuilder initialSettings(Http2Settings settings) {
76          return super.initialSettings(settings);
77      }
78  
79      @Override
80      public long gracefulShutdownTimeoutMillis() {
81          return super.gracefulShutdownTimeoutMillis();
82      }
83  
84      @Override
85      public Http2FrameCodecBuilder gracefulShutdownTimeoutMillis(long gracefulShutdownTimeoutMillis) {
86          return super.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis);
87      }
88  
89      @Override
90      public boolean isServer() {
91          return super.isServer();
92      }
93  
94      @Override
95      public int maxReservedStreams() {
96          return super.maxReservedStreams();
97      }
98  
99      @Override
100     public Http2FrameCodecBuilder maxReservedStreams(int maxReservedStreams) {
101         return super.maxReservedStreams(maxReservedStreams);
102     }
103 
104     @Override
105     public boolean isValidateHeaders() {
106         return super.isValidateHeaders();
107     }
108 
109     @Override
110     public Http2FrameCodecBuilder validateHeaders(boolean validateHeaders) {
111         return super.validateHeaders(validateHeaders);
112     }
113 
114     @Override
115     public Http2FrameLogger frameLogger() {
116         return super.frameLogger();
117     }
118 
119     @Override
120     public Http2FrameCodecBuilder frameLogger(Http2FrameLogger frameLogger) {
121         return super.frameLogger(frameLogger);
122     }
123 
124     @Override
125     public boolean encoderEnforceMaxConcurrentStreams() {
126         return super.encoderEnforceMaxConcurrentStreams();
127     }
128 
129     @Override
130     public Http2FrameCodecBuilder encoderEnforceMaxConcurrentStreams(boolean encoderEnforceMaxConcurrentStreams) {
131         return super.encoderEnforceMaxConcurrentStreams(encoderEnforceMaxConcurrentStreams);
132     }
133 
134     @Override
135     public int encoderEnforceMaxQueuedControlFrames() {
136         return super.encoderEnforceMaxQueuedControlFrames();
137     }
138 
139     @Override
140     public Http2FrameCodecBuilder encoderEnforceMaxQueuedControlFrames(int maxQueuedControlFrames) {
141         return super.encoderEnforceMaxQueuedControlFrames(maxQueuedControlFrames);
142     }
143 
144     @Override
145     public Http2HeadersEncoder.SensitivityDetector headerSensitivityDetector() {
146         return super.headerSensitivityDetector();
147     }
148 
149     @Override
150     public Http2FrameCodecBuilder headerSensitivityDetector(
151             Http2HeadersEncoder.SensitivityDetector headerSensitivityDetector) {
152         return super.headerSensitivityDetector(headerSensitivityDetector);
153     }
154 
155     @Override
156     public Http2FrameCodecBuilder encoderIgnoreMaxHeaderListSize(boolean ignoreMaxHeaderListSize) {
157         return super.encoderIgnoreMaxHeaderListSize(ignoreMaxHeaderListSize);
158     }
159 
160     @Override
161     @Deprecated
162     public Http2FrameCodecBuilder initialHuffmanDecodeCapacity(int initialHuffmanDecodeCapacity) {
163         return super.initialHuffmanDecodeCapacity(initialHuffmanDecodeCapacity);
164     }
165 
166     @Override
167     public Http2FrameCodecBuilder autoAckSettingsFrame(boolean autoAckSettings) {
168         return super.autoAckSettingsFrame(autoAckSettings);
169     }
170 
171     @Override
172     public Http2FrameCodecBuilder autoAckPingFrame(boolean autoAckPingFrame) {
173         return super.autoAckPingFrame(autoAckPingFrame);
174     }
175 
176     @Override
177     public Http2FrameCodecBuilder decoupleCloseAndGoAway(boolean decoupleCloseAndGoAway) {
178         return super.decoupleCloseAndGoAway(decoupleCloseAndGoAway);
179     }
180 
181     @Override
182     public Http2FrameCodecBuilder flushPreface(boolean flushPreface) {
183         return super.flushPreface(flushPreface);
184     }
185 
186     @Override
187     public int decoderEnforceMaxConsecutiveEmptyDataFrames() {
188         return super.decoderEnforceMaxConsecutiveEmptyDataFrames();
189     }
190 
191     @Override
192     public Http2FrameCodecBuilder decoderEnforceMaxConsecutiveEmptyDataFrames(int maxConsecutiveEmptyFrames) {
193         return super.decoderEnforceMaxConsecutiveEmptyDataFrames(maxConsecutiveEmptyFrames);
194     }
195 
196     /**
197      * Build a {@link Http2FrameCodec} object.
198      */
199     @Override
200     public Http2FrameCodec build() {
201         Http2FrameWriter frameWriter = this.frameWriter;
202         if (frameWriter != null) {
203             // This is to support our tests and will never be executed by the user as frameWriter(...)
204             // is package-private.
205             DefaultHttp2Connection connection = new DefaultHttp2Connection(isServer(), maxReservedStreams());
206             Long maxHeaderListSize = initialSettings().maxHeaderListSize();
207             Http2FrameReader frameReader = new DefaultHttp2FrameReader(maxHeaderListSize == null ?
208                     new DefaultHttp2HeadersDecoder(isValidateHeaders()) :
209                     new DefaultHttp2HeadersDecoder(isValidateHeaders(), maxHeaderListSize));
210 
211             if (frameLogger() != null) {
212                 frameWriter = new Http2OutboundFrameLogger(frameWriter, frameLogger());
213                 frameReader = new Http2InboundFrameLogger(frameReader, frameLogger());
214             }
215             Http2ConnectionEncoder encoder = new DefaultHttp2ConnectionEncoder(connection, frameWriter);
216             if (encoderEnforceMaxConcurrentStreams()) {
217                 encoder = new StreamBufferingEncoder(encoder);
218             }
219             Http2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder(connection, encoder, frameReader,
220                     promisedRequestVerifier(), isAutoAckSettingsFrame(), isAutoAckPingFrame());
221             int maxConsecutiveEmptyDataFrames = decoderEnforceMaxConsecutiveEmptyDataFrames();
222             if (maxConsecutiveEmptyDataFrames > 0) {
223                 decoder = new Http2EmptyDataFrameConnectionDecoder(decoder, maxConsecutiveEmptyDataFrames);
224             }
225             return build(decoder, encoder, initialSettings());
226         }
227         return super.build();
228     }
229 
230     @Override
231     protected Http2FrameCodec build(
232             Http2ConnectionDecoder decoder, Http2ConnectionEncoder encoder, Http2Settings initialSettings) {
233         Http2FrameCodec codec = new Http2FrameCodec(encoder, decoder, initialSettings,
234                 decoupleCloseAndGoAway(), flushPreface());
235         codec.gracefulShutdownTimeoutMillis(gracefulShutdownTimeoutMillis());
236         return codec;
237     }
238 }