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.WebSocketExtensionData;
19  import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionDecoder;
20  import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionEncoder;
21  import io.netty.handler.codec.http.websocketx.extensions.WebSocketExtensionFilterProvider;
22  import io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtension;
23  import io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandshaker;
24  
25  import java.util.Collections;
26  
27  import static io.netty.util.internal.ObjectUtil.*;
28  
29  /**
30   * <a href="https://tools.ietf.org/id/draft-tyoshino-hybi-websocket-perframe-deflate-06.txt">perframe-deflate</a>
31   * handshake implementation.
32   */
33  public final class DeflateFrameServerExtensionHandshaker implements WebSocketServerExtensionHandshaker {
34  
35      static final String X_WEBKIT_DEFLATE_FRAME_EXTENSION = "x-webkit-deflate-frame";
36      static final String DEFLATE_FRAME_EXTENSION = "deflate-frame";
37  
38      private final int compressionLevel;
39      private final WebSocketExtensionFilterProvider extensionFilterProvider;
40  
41      /**
42       * Constructor with default configuration.
43       */
44      public DeflateFrameServerExtensionHandshaker() {
45          this(6);
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 DeflateFrameServerExtensionHandshaker(int compressionLevel) {
55          this(compressionLevel, 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 server extension filters for per frame deflate encoder and decoder.
65       */
66      public DeflateFrameServerExtensionHandshaker(int compressionLevel,
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.extensionFilterProvider = checkNotNull(extensionFilterProvider, "extensionFilterProvider");
74      }
75  
76      @Override
77      public WebSocketServerExtension handshakeExtension(WebSocketExtensionData extensionData) {
78          if (!X_WEBKIT_DEFLATE_FRAME_EXTENSION.equals(extensionData.name()) &&
79              !DEFLATE_FRAME_EXTENSION.equals(extensionData.name())) {
80              return null;
81          }
82  
83          if (extensionData.parameters().isEmpty()) {
84              return new DeflateFrameServerExtension(compressionLevel, extensionData.name(), extensionFilterProvider);
85          } else {
86              return null;
87          }
88      }
89  
90      private static class DeflateFrameServerExtension implements WebSocketServerExtension {
91  
92          private final String extensionName;
93          private final int compressionLevel;
94          private final WebSocketExtensionFilterProvider extensionFilterProvider;
95  
96          DeflateFrameServerExtension(int compressionLevel, String extensionName,
97                  WebSocketExtensionFilterProvider extensionFilterProvider) {
98              this.extensionName = extensionName;
99              this.compressionLevel = compressionLevel;
100             this.extensionFilterProvider = extensionFilterProvider;
101         }
102 
103         @Override
104         public int rsv() {
105             return RSV1;
106         }
107 
108         @Override
109         public WebSocketExtensionEncoder newExtensionEncoder() {
110             return new PerFrameDeflateEncoder(compressionLevel, 15, false,
111                                               extensionFilterProvider.encoderFilter());
112         }
113 
114         @Override
115         public WebSocketExtensionDecoder newExtensionDecoder() {
116             return new PerFrameDeflateDecoder(false, extensionFilterProvider.decoderFilter());
117         }
118 
119         @Override
120         public WebSocketExtensionData newReponseData() {
121             return new WebSocketExtensionData(extensionName, Collections.<String, String>emptyMap());
122         }
123     }
124 
125 }