1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http.websocket;
17
18 import org.jboss.netty.buffer.ChannelBuffer;
19 import org.jboss.netty.channel.Channel;
20 import org.jboss.netty.channel.ChannelHandlerContext;
21 import org.jboss.netty.handler.codec.frame.TooLongFrameException;
22 import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
23 import org.jboss.netty.handler.codec.replay.VoidEnum;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public class WebSocketFrameDecoder extends ReplayingDecoder<VoidEnum> {
41
42 public static final int DEFAULT_MAX_FRAME_SIZE = 16384;
43
44 private final int maxFrameSize;
45 private boolean receivedClosingHandshake;
46
47 public WebSocketFrameDecoder() {
48 this(DEFAULT_MAX_FRAME_SIZE);
49 }
50
51
52
53
54
55
56
57 public WebSocketFrameDecoder(int maxFrameSize) {
58 this.maxFrameSize = maxFrameSize;
59 }
60
61 @Override
62 protected Object decode(ChannelHandlerContext ctx, Channel channel,
63 ChannelBuffer buffer, VoidEnum state) throws Exception {
64
65
66 if (receivedClosingHandshake) {
67 buffer.skipBytes(actualReadableBytes());
68 return null;
69 }
70
71
72 byte type = buffer.readByte();
73 if ((type & 0x80) == 0x80) {
74
75 return decodeBinaryFrame(type, buffer);
76 } else {
77
78 return decodeTextFrame(type, buffer);
79 }
80 }
81
82 private WebSocketFrame decodeBinaryFrame(int type, ChannelBuffer buffer) throws TooLongFrameException {
83 long frameSize = 0;
84 int lengthFieldSize = 0;
85 byte b;
86 do {
87 b = buffer.readByte();
88 frameSize <<= 7;
89 frameSize |= b & 0x7f;
90 if (frameSize > maxFrameSize) {
91 throw new TooLongFrameException();
92 }
93 lengthFieldSize ++;
94 if (lengthFieldSize > 8) {
95
96 throw new TooLongFrameException();
97 }
98 } while ((b & 0x80) == 0x80);
99
100 if (type == 0xFF && frameSize == 0) {
101 receivedClosingHandshake = true;
102 }
103
104 return new DefaultWebSocketFrame(
105 type, buffer.readBytes((int) frameSize));
106 }
107
108 private WebSocketFrame decodeTextFrame(int type, ChannelBuffer buffer) throws TooLongFrameException {
109 int ridx = buffer.readerIndex();
110 int rbytes = actualReadableBytes();
111 int delimPos = buffer.indexOf(ridx, ridx + rbytes, (byte) 0xFF);
112 if (delimPos == -1) {
113
114 if (rbytes > maxFrameSize) {
115
116 throw new TooLongFrameException();
117 } else {
118
119 return null;
120 }
121 }
122
123 int frameSize = delimPos - ridx;
124 if (frameSize > maxFrameSize) {
125 throw new TooLongFrameException();
126 }
127
128 ChannelBuffer binaryData = buffer.readBytes(frameSize);
129 buffer.skipBytes(1);
130 return new DefaultWebSocketFrame(type, binaryData);
131 }
132 }