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    *   http://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.buffer.Unpooled;
20  import io.netty.channel.ChannelFutureListener;
21  import io.netty.channel.ChannelHandlerContext;
22  import io.netty.channel.ChannelInboundHandlerAdapter;
23  import io.netty.handler.codec.CorruptedFrameException;
24  
25  /**
26   *
27   */
28  public class Utf8FrameValidator extends ChannelInboundHandlerAdapter {
29  
30      private int fragmentedFramesCount;
31      private Utf8Validator utf8Validator;
32  
33      @Override
34      public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
35          if (msg instanceof WebSocketFrame) {
36              WebSocketFrame frame = (WebSocketFrame) msg;
37  
38              try {
39                  // Processing for possible fragmented messages for text and binary
40                  // frames
41                  if (((WebSocketFrame) msg).isFinalFragment()) {
42                      // Final frame of the sequence. Apparently ping frames are
43                      // allowed in the middle of a fragmented message
44                      if (!(frame instanceof PingWebSocketFrame)) {
45                          fragmentedFramesCount = 0;
46  
47                          // Check text for UTF8 correctness
48                          if ((frame instanceof TextWebSocketFrame) ||
49                                  (utf8Validator != null && utf8Validator.isChecking())) {
50                              // Check UTF-8 correctness for this payload
51                              checkUTF8String(frame.content());
52  
53                              // This does a second check to make sure UTF-8
54                              // correctness for entire text message
55                              utf8Validator.finish();
56                          }
57                      }
58                  } else {
59                      // Not final frame so we can expect more frames in the
60                      // fragmented sequence
61                      if (fragmentedFramesCount == 0) {
62                          // First text or binary frame for a fragmented set
63                          if (frame instanceof TextWebSocketFrame) {
64                              checkUTF8String(frame.content());
65                          }
66                      } else {
67                          // Subsequent frames - only check if init frame is text
68                          if (utf8Validator != null && utf8Validator.isChecking()) {
69                              checkUTF8String(frame.content());
70                          }
71                      }
72  
73                      // Increment counter
74                      fragmentedFramesCount++;
75                  }
76              } catch (CorruptedWebSocketFrameException e) {
77                  frame.release();
78                  throw e;
79              }
80          }
81  
82          super.channelRead(ctx, msg);
83      }
84  
85      private void checkUTF8String(ByteBuf buffer) {
86          if (utf8Validator == null) {
87              utf8Validator = new Utf8Validator();
88          }
89          utf8Validator.check(buffer);
90      }
91  
92      @Override
93      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
94          if (cause instanceof CorruptedFrameException && ctx.channel().isOpen()) {
95              ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
96          }
97          super.exceptionCaught(ctx, cause);
98      }
99  }