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