1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http.websocketx;
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 public class WebSocket00FrameDecoder extends ReplayingDecoder<VoidEnum> {
35
36 private static final int DEFAULT_MAX_FRAME_SIZE = 16384;
37
38 private final long maxFrameSize;
39 private boolean receivedClosingHandshake;
40
41 public WebSocket00FrameDecoder() {
42 this(DEFAULT_MAX_FRAME_SIZE);
43 }
44
45
46
47
48
49
50
51
52
53 @Deprecated
54 public WebSocket00FrameDecoder(int maxFrameSize) {
55 this.maxFrameSize = maxFrameSize;
56 }
57
58
59
60
61
62
63
64
65 public WebSocket00FrameDecoder(long maxFrameSize) {
66 this.maxFrameSize = maxFrameSize;
67 }
68
69 @Override
70 protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, VoidEnum state)
71 throws Exception {
72
73
74 if (receivedClosingHandshake) {
75 buffer.skipBytes(actualReadableBytes());
76 return null;
77 }
78
79
80 byte type = buffer.readByte();
81 if ((type & 0x80) == 0x80) {
82
83 return decodeBinaryFrame(type, buffer);
84 } else {
85
86 return decodeTextFrame(buffer);
87 }
88 }
89
90 private WebSocketFrame decodeBinaryFrame(byte type, ChannelBuffer buffer) throws TooLongFrameException {
91 long frameSize = 0;
92 int lengthFieldSize = 0;
93 byte b;
94 do {
95 b = buffer.readByte();
96 frameSize <<= 7;
97 frameSize |= b & 0x7f;
98 if (frameSize > maxFrameSize) {
99 throw new TooLongFrameException();
100 }
101 lengthFieldSize++;
102 if (lengthFieldSize > 8) {
103
104 throw new TooLongFrameException();
105 }
106 } while ((b & 0x80) == 0x80);
107
108 if (type == (byte) 0xFF && frameSize == 0) {
109 receivedClosingHandshake = true;
110 return new CloseWebSocketFrame();
111 }
112
113 return new BinaryWebSocketFrame(buffer.readBytes((int) frameSize));
114 }
115
116 private WebSocketFrame decodeTextFrame(ChannelBuffer buffer) throws TooLongFrameException {
117 int ridx = buffer.readerIndex();
118 int rbytes = actualReadableBytes();
119 int delimPos = buffer.indexOf(ridx, ridx + rbytes, (byte) 0xFF);
120 if (delimPos == -1) {
121
122 if (rbytes > maxFrameSize) {
123
124 throw new TooLongFrameException();
125 } else {
126
127 return null;
128 }
129 }
130
131 int frameSize = delimPos - ridx;
132 if (frameSize > maxFrameSize) {
133 throw new TooLongFrameException();
134 }
135
136 ChannelBuffer binaryData = buffer.readBytes(frameSize);
137 buffer.skipBytes(1);
138
139 int ffDelimPos = binaryData.indexOf(binaryData.readerIndex(), binaryData.writerIndex(), (byte) 0xFF);
140 if (ffDelimPos >= 0) {
141 throw new IllegalArgumentException("a text frame should not contain 0xFF.");
142 }
143
144 return new TextWebSocketFrame(binaryData);
145 }
146 }