1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 package org.eclipse.jetty.websocket;
30
31 import java.io.IOException;
32
33 import org.eclipse.jetty.io.Buffer;
34 import org.eclipse.jetty.io.Buffers;
35 import org.eclipse.jetty.io.EndPoint;
36 import org.eclipse.jetty.util.log.Log;
37 import org.eclipse.jetty.util.log.Logger;
38
39
40
41
42
43
44
45
46 public class WebSocketParserD06 implements WebSocketParser
47 {
48 private static final Logger LOG = Log.getLogger(WebSocketParserD06.class);
49
50 public enum State {
51
52 START(0), MASK(4), OPCODE(1), LENGTH_7(1), LENGTH_16(2), LENGTH_63(8), DATA(0), SKIP(1);
53
54 int _needs;
55
56 State(int needs)
57 {
58 _needs=needs;
59 }
60
61 int getNeeds()
62 {
63 return _needs;
64 }
65 }
66
67
68 private final WebSocketBuffers _buffers;
69 private final EndPoint _endp;
70 private final FrameHandler _handler;
71 private final boolean _masked;
72 private State _state;
73 private Buffer _buffer;
74 private byte _flags;
75 private byte _opcode;
76 private int _bytesNeeded;
77 private long _length;
78 private final byte[] _mask = new byte[4];
79 private int _m;
80
81
82
83
84
85
86
87
88
89
90 public WebSocketParserD06(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler, boolean masked)
91 {
92 _buffers=buffers;
93 _endp=endp;
94 _handler=handler;
95 _masked=masked;
96 _state=State.START;
97 }
98
99
100 public boolean isBufferEmpty()
101 {
102 return _buffer==null || _buffer.length()==0;
103 }
104
105
106 public Buffer getBuffer()
107 {
108 return _buffer;
109 }
110
111
112
113
114
115
116
117
118
119 public int parseNext()
120 {
121 if (_buffer==null)
122 _buffer=_buffers.getBuffer();
123
124 int total_filled=0;
125 int events=0;
126
127
128 while(true)
129 {
130 int available=_buffer.length();
131
132
133 while (available<(_state==State.SKIP?1:_bytesNeeded))
134 {
135
136 _buffer.compact();
137
138
139 if (_buffer.space() == 0)
140 throw new IllegalStateException("FULL: "+_state+" "+_bytesNeeded+">"+_buffer.capacity());
141
142
143 try
144 {
145 int filled=_endp.isOpen()?_endp.fill(_buffer):-1;
146 if (filled<=0)
147 return (total_filled+events)>0?(total_filled+events):filled;
148 total_filled+=filled;
149 available=_buffer.length();
150 }
151 catch(IOException e)
152 {
153 LOG.debug(e);
154 return (total_filled+events)>0?(total_filled+events):-1;
155 }
156 }
157
158
159
160
161 byte b;
162 while (_state!=State.DATA && available>=(_state==State.SKIP?1:_bytesNeeded))
163 {
164 switch (_state)
165 {
166 case START:
167 _state=_masked?State.MASK:State.OPCODE;
168 _bytesNeeded=_state.getNeeds();
169 continue;
170
171 case MASK:
172 _buffer.get(_mask,0,4);
173 available-=4;
174 _state=State.OPCODE;
175 _bytesNeeded=_state.getNeeds();
176 _m=0;
177 continue;
178
179 case OPCODE:
180 b=_buffer.get();
181 available--;
182 if (_masked)
183 b^=_mask[_m++%4];
184 _opcode=(byte)(b&0xf);
185 _flags=(byte)(0xf&(b>>4));
186
187 if (WebSocketConnectionD06.isControlFrame(_opcode)&&!WebSocketConnectionD06.isLastFrame(_flags))
188 {
189 _state=State.SKIP;
190 events++;
191 _handler.close(WebSocketConnectionD06.CLOSE_PROTOCOL,"fragmented control");
192 }
193 else
194 _state=State.LENGTH_7;
195
196 _bytesNeeded=_state.getNeeds();
197 continue;
198
199 case LENGTH_7:
200 b=_buffer.get();
201 available--;
202 if (_masked)
203 b^=_mask[_m++%4];
204 switch(b)
205 {
206 case 127:
207 _length=0;
208 _state=State.LENGTH_63;
209 _bytesNeeded=_state.getNeeds();
210 break;
211 case 126:
212 _length=0;
213 _state=State.LENGTH_16;
214 _bytesNeeded=_state.getNeeds();
215 break;
216 default:
217 _length=(0x7f&b);
218 _bytesNeeded=(int)_length;
219 _state=State.DATA;
220 }
221 continue;
222
223 case LENGTH_16:
224 b=_buffer.get();
225 available--;
226 if (_masked)
227 b^=_mask[_m++%4];
228 _length = _length*0x100 + (0xff&b);
229 if (--_bytesNeeded==0)
230 {
231 _bytesNeeded=(int)_length;
232 if (_length>_buffer.capacity())
233 {
234 _state=State.SKIP;
235 events++;
236 _handler.close(WebSocketConnectionD06.CLOSE_LARGE,"frame size "+_length+">"+_buffer.capacity());
237 }
238 else
239 {
240 _state=State.DATA;
241 }
242 }
243 continue;
244
245 case LENGTH_63:
246 b=_buffer.get();
247 available--;
248 if (_masked)
249 b^=_mask[_m++%4];
250 _length = _length*0x100 + (0xff&b);
251 if (--_bytesNeeded==0)
252 {
253 _bytesNeeded=(int)_length;
254 if (_length>=_buffer.capacity())
255 {
256 _state=State.SKIP;
257 events++;
258 _handler.close(WebSocketConnectionD06.CLOSE_LARGE,"frame size "+_length+">"+_buffer.capacity());
259 }
260 else
261 {
262 _state=State.DATA;
263 }
264 }
265 continue;
266
267 case SKIP:
268 int skip=Math.min(available,_bytesNeeded);
269 _buffer.skip(skip);
270 available-=skip;
271 _bytesNeeded-=skip;
272 if (_bytesNeeded==0)
273 _state=State.START;
274
275 }
276 }
277
278 if (_state==State.DATA && available>=_bytesNeeded)
279 {
280 Buffer data =_buffer.get(_bytesNeeded);
281 if (_masked)
282 {
283 if (data.array()==null)
284 data=_buffer.asMutableBuffer();
285 byte[] array = data.array();
286 final int end=data.putIndex();
287 for (int i=data.getIndex();i<end;i++)
288 array[i]^=_mask[_m++%4];
289 }
290
291
292 events++;
293 _handler.onFrame(_flags, _opcode, data);
294 _bytesNeeded=0;
295 _state=State.START;
296
297 if (_buffer.length()==0)
298 {
299 _buffers.returnBuffer(_buffer);
300 _buffer=null;
301 }
302
303 return total_filled+events;
304 }
305 }
306 }
307
308
309 public void fill(Buffer buffer)
310 {
311 if (buffer!=null && buffer.length()>0)
312 {
313 if (_buffer==null)
314 _buffer=_buffers.getBuffer();
315 _buffer.put(buffer);
316 buffer.clear();
317 }
318 }
319
320 }