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