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 long 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 public WebSocket00FrameDecoder(long maxFrameSize) {
53 this.maxFrameSize = maxFrameSize;
54 }
55
56 @Override
57 protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, VoidEnum state)
58 throws Exception {
59
60
61 if (receivedClosingHandshake) {
62 buffer.skipBytes(actualReadableBytes());
63 return null;
64 }
65
66
67 byte type = buffer.readByte();
68 if ((type & 0x80) == 0x80) {
69
70 return decodeBinaryFrame(type, buffer);
71 } else {
72
73 return decodeTextFrame(buffer);
74 }
75 }
76
77 private WebSocketFrame decodeBinaryFrame(byte type, ChannelBuffer buffer) throws TooLongFrameException {
78 long frameSize = 0;
79 int lengthFieldSize = 0;
80 byte b;
81 do {
82 b = buffer.readByte();
83 frameSize <<= 7;
84 frameSize |= b & 0x7f;
85 if (frameSize > maxFrameSize) {
86 throw new TooLongFrameException();
87 }
88 lengthFieldSize++;
89 if (lengthFieldSize > 8) {
90
91 throw new TooLongFrameException();
92 }
93 } while ((b & 0x80) == 0x80);
94
95 if (type == (byte) 0xFF && frameSize == 0) {
96 receivedClosingHandshake = true;
97 return new CloseWebSocketFrame();
98 }
99
100 return new BinaryWebSocketFrame(buffer.readBytes((int) frameSize));
101 }
102
103 private WebSocketFrame decodeTextFrame(ChannelBuffer buffer) throws TooLongFrameException {
104 int ridx = buffer.readerIndex();
105 int rbytes = actualReadableBytes();
106 int delimPos = buffer.indexOf(ridx, ridx + rbytes, (byte) 0xFF);
107 if (delimPos == -1) {
108
109 if (rbytes > maxFrameSize) {
110
111 throw new TooLongFrameException();
112 } else {
113
114 return null;
115 }
116 }
117
118 int frameSize = delimPos - ridx;
119 if (frameSize > maxFrameSize) {
120 throw new TooLongFrameException();
121 }
122
123 ChannelBuffer binaryData = buffer.readBytes(frameSize);
124 buffer.skipBytes(1);
125
126 int ffDelimPos = binaryData.indexOf(binaryData.readerIndex(), binaryData.writerIndex(), (byte) 0xFF);
127 if (ffDelimPos >= 0) {
128 throw new IllegalArgumentException("a text frame should not contain 0xFF.");
129 }
130
131 return new TextWebSocketFrame(binaryData);
132 }
133 }