View Javadoc
1   /*
2    * Copyright 2013 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;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.channel.ChannelPipeline;
20  import io.netty.handler.codec.MessageAggregator;
21  import io.netty.handler.codec.TooLongFrameException;
22  
23  /**
24   * Handler that aggregate fragmented WebSocketFrame's.
25   *
26   * Be aware if PING/PONG/CLOSE frames are send in the middle of a fragmented {@link WebSocketFrame} they will
27   * just get forwarded to the next handler in the pipeline.
28   */
29  public class WebSocketFrameAggregator
30          extends MessageAggregator<WebSocketFrame, WebSocketFrame, ContinuationWebSocketFrame, WebSocketFrame> {
31  
32      /**
33       * Creates a new instance
34       *
35       * @param maxContentLength If the size of the aggregated frame exceeds this value,
36       *                         a {@link TooLongFrameException} is thrown.
37       */
38      public WebSocketFrameAggregator(int maxContentLength) {
39          super(maxContentLength);
40      }
41  
42      @Override
43      protected boolean isStartMessage(WebSocketFrame msg) throws Exception {
44          return msg instanceof TextWebSocketFrame || msg instanceof BinaryWebSocketFrame;
45      }
46  
47      @Override
48      protected boolean isContentMessage(WebSocketFrame msg) throws Exception {
49          return msg instanceof ContinuationWebSocketFrame;
50      }
51  
52      @Override
53      protected boolean isLastContentMessage(ContinuationWebSocketFrame msg) throws Exception {
54          return isContentMessage(msg) && msg.isFinalFragment();
55      }
56  
57      @Override
58      protected boolean isAggregated(WebSocketFrame msg) throws Exception {
59          if (msg.isFinalFragment()) {
60              return !isContentMessage(msg);
61          }
62  
63          return !isStartMessage(msg) && !isContentMessage(msg);
64      }
65  
66      @Override
67      protected boolean isContentLengthInvalid(WebSocketFrame start, int maxContentLength) {
68          return false;
69      }
70  
71      @Override
72      protected Object newContinueResponse(WebSocketFrame start, int maxContentLength, ChannelPipeline pipeline) {
73          return null;
74      }
75  
76      @Override
77      protected boolean closeAfterContinueResponse(Object msg) throws Exception {
78          throw new UnsupportedOperationException();
79      }
80  
81      @Override
82      protected boolean ignoreContentAfterContinueResponse(Object msg) throws Exception {
83          throw new UnsupportedOperationException();
84      }
85  
86      @Override
87      protected WebSocketFrame beginAggregation(WebSocketFrame start, ByteBuf content) throws Exception {
88          if (start instanceof TextWebSocketFrame) {
89              return new TextWebSocketFrame(true, start.rsv(), content);
90          }
91  
92          if (start instanceof BinaryWebSocketFrame) {
93              return new BinaryWebSocketFrame(true, start.rsv(), content);
94          }
95  
96          // Should not reach here.
97          throw new Error();
98      }
99  }