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