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