View Javadoc
1   /*
2    * Copyright 2014 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.http.websocketx.extensions.compression;
17  
18  import io.netty5.handler.codec.http.websocketx.extensions.WebSocketClientExtension;
19  import io.netty5.handler.codec.http.websocketx.extensions.WebSocketClientExtensionHandshaker;
20  import io.netty5.handler.codec.http.websocketx.extensions.WebSocketExtensionData;
21  import io.netty5.handler.codec.http.websocketx.extensions.WebSocketExtensionDecoder;
22  import io.netty5.handler.codec.http.websocketx.extensions.WebSocketExtensionEncoder;
23  import io.netty5.handler.codec.http.websocketx.extensions.WebSocketExtensionFilterProvider;
24  
25  import java.util.Collections;
26  import java.util.Objects;
27  
28  import static io.netty5.handler.codec.http.websocketx.extensions.compression.DeflateFrameServerExtensionHandshaker.DEFLATE_FRAME_EXTENSION;
29  import static io.netty5.handler.codec.http.websocketx.extensions.compression.DeflateFrameServerExtensionHandshaker.X_WEBKIT_DEFLATE_FRAME_EXTENSION;
30  
31  /**
32   * <a href="https://tools.ietf.org/id/draft-tyoshino-hybi-websocket-perframe-deflate-06.txt">perframe-deflate</a>
33   * handshake implementation.
34   */
35  public final class DeflateFrameClientExtensionHandshaker implements WebSocketClientExtensionHandshaker {
36  
37      private final int compressionLevel;
38      private final boolean useWebkitExtensionName;
39      private final WebSocketExtensionFilterProvider extensionFilterProvider;
40  
41      /**
42       * Constructor with default configuration.
43       */
44      public DeflateFrameClientExtensionHandshaker(boolean useWebkitExtensionName) {
45          this(6, useWebkitExtensionName);
46      }
47  
48      /**
49       * Constructor with custom configuration.
50       *
51       * @param compressionLevel
52       *            Compression level between 0 and 9 (default is 6).
53       */
54      public DeflateFrameClientExtensionHandshaker(int compressionLevel, boolean useWebkitExtensionName) {
55          this(compressionLevel, useWebkitExtensionName, WebSocketExtensionFilterProvider.DEFAULT);
56      }
57  
58      /**
59       * Constructor with custom configuration.
60       *
61       * @param compressionLevel
62       *            Compression level between 0 and 9 (default is 6).
63       * @param extensionFilterProvider
64       *            provides client extension filters for per frame deflate encoder and decoder.
65       */
66      public DeflateFrameClientExtensionHandshaker(int compressionLevel, boolean useWebkitExtensionName,
67              WebSocketExtensionFilterProvider extensionFilterProvider) {
68          if (compressionLevel < 0 || compressionLevel > 9) {
69              throw new IllegalArgumentException(
70                      "compressionLevel: " + compressionLevel + " (expected: 0-9)");
71          }
72          this.compressionLevel = compressionLevel;
73          this.useWebkitExtensionName = useWebkitExtensionName;
74          this.extensionFilterProvider = Objects.requireNonNull(extensionFilterProvider, "extensionFilterProvider");
75      }
76  
77      @Override
78      public WebSocketExtensionData newRequestData() {
79          return new WebSocketExtensionData(
80                  useWebkitExtensionName ? X_WEBKIT_DEFLATE_FRAME_EXTENSION : DEFLATE_FRAME_EXTENSION,
81                  Collections.emptyMap());
82      }
83  
84      @Override
85      public WebSocketClientExtension handshakeExtension(WebSocketExtensionData extensionData) {
86          if (!X_WEBKIT_DEFLATE_FRAME_EXTENSION.equals(extensionData.name()) &&
87              !DEFLATE_FRAME_EXTENSION.equals(extensionData.name())) {
88              return null;
89          }
90  
91          if (extensionData.parameters().isEmpty()) {
92              return new DeflateFrameClientExtension(compressionLevel, extensionFilterProvider);
93          } else {
94              return null;
95          }
96      }
97  
98      private static class DeflateFrameClientExtension implements WebSocketClientExtension {
99  
100         private final int compressionLevel;
101         private final WebSocketExtensionFilterProvider extensionFilterProvider;
102 
103         DeflateFrameClientExtension(int compressionLevel, WebSocketExtensionFilterProvider extensionFilterProvider) {
104             this.compressionLevel = compressionLevel;
105             this.extensionFilterProvider = extensionFilterProvider;
106         }
107 
108         @Override
109         public int rsv() {
110             return RSV1;
111         }
112 
113         @Override
114         public WebSocketExtensionEncoder newExtensionEncoder() {
115             return new PerFrameDeflateEncoder(compressionLevel, 15, false,
116                                               extensionFilterProvider.encoderFilter());
117         }
118 
119         @Override
120         public WebSocketExtensionDecoder newExtensionDecoder() {
121             return new PerFrameDeflateDecoder(false, extensionFilterProvider.decoderFilter());
122         }
123     }
124 
125 }