1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.websocket;
15
16 import java.io.IOException;
17
18 import org.eclipse.jetty.io.Buffer;
19 import org.eclipse.jetty.io.Buffers;
20 import org.eclipse.jetty.io.EndPoint;
21 import org.eclipse.jetty.util.Utf8StringBuilder;
22 import org.eclipse.jetty.util.log.Log;
23
24
25
26
27
28
29
30
31 public class WebSocketParserD01 implements WebSocketParser
32 {
33 public enum State {
34 START(1), LENGTH_7(2), LENGTH_16(4), LENGTH_63(10), DATA(10);
35
36 int _minSize;
37
38 State(int minSize)
39 {
40 _minSize=minSize;
41 }
42
43 int getMinSize()
44 {
45 return _minSize;
46 }
47 };
48
49
50 private final WebSocketBuffers _buffers;
51 private final EndPoint _endp;
52 private final FrameHandler _handler;
53 private State _state=State.START;
54 private Buffer _buffer;
55 private boolean _more;
56 private byte _flags;
57 private byte _opcode;
58 private int _count;
59 private long _length;
60 private Utf8StringBuilder _utf8;
61
62
63
64
65
66
67
68
69
70 public WebSocketParserD01(WebSocketBuffers buffers, EndPoint endp, FrameHandler handler)
71 {
72 _buffers=buffers;
73 _endp=endp;
74 _handler=handler;
75 }
76
77
78 public boolean isBufferEmpty()
79 {
80 return _buffer==null || _buffer.length()==0;
81 }
82
83
84 public Buffer getBuffer()
85 {
86 return _buffer;
87 }
88
89
90
91
92
93
94
95
96
97 public int parseNext()
98 {
99 if (_buffer==null)
100 _buffer=_buffers.getBuffer();
101
102 int total_filled=0;
103
104
105 while(true)
106 {
107 int available=_buffer.length();
108
109
110 if (available < _state.getMinSize() || _state==State.DATA && available<_count)
111 {
112
113 _buffer.compact();
114
115
116 if (_buffer.space() == 0)
117 throw new IllegalStateException("FULL");
118
119
120 try
121 {
122 int filled=_endp.isOpen()?_endp.fill(_buffer):-1;
123 if (filled<=0)
124 return total_filled;
125 total_filled+=filled;
126 available=_buffer.length();
127 }
128 catch(IOException e)
129 {
130 Log.debug(e);
131 return total_filled>0?total_filled:-1;
132 }
133 }
134
135
136 byte b;
137 while (_state!=State.DATA && available-->0)
138 {
139 switch (_state)
140 {
141 case START:
142 b=_buffer.get();
143 _opcode=(byte)(b&0xf);
144 _flags=(byte)(b>>4);
145 _more=(_flags&8)!=0;
146 _state=State.LENGTH_7;
147 continue;
148
149 case LENGTH_7:
150 b=_buffer.get();
151 switch(b)
152 {
153 case 127:
154 _length=0;
155 _count=8;
156 _state=State.LENGTH_63;
157 break;
158 case 126:
159 _length=0;
160 _count=2;
161 _state=State.LENGTH_16;
162 break;
163 default:
164 _length=(0x7f&b);
165 _count=(int)_length;
166 _state=State.DATA;
167 }
168 continue;
169
170 case LENGTH_16:
171 b=_buffer.get();
172 _length = _length<<8 | b;
173 if (--_count==0)
174 {
175 if (_length>=_buffer.capacity()-4)
176 throw new IllegalStateException("TOO LARGE");
177 _count=(int)_length;
178 _state=State.DATA;
179 }
180 continue;
181
182 case LENGTH_63:
183 b=_buffer.get();
184 _length = _length<<8 | b;
185 if (--_count==0)
186 {
187 if (_length>=_buffer.capacity()-10)
188 throw new IllegalStateException("TOO LARGE");
189 _count=(int)_length;
190 _state=State.DATA;
191 }
192 continue;
193 }
194 }
195
196 if (_state==State.DATA && available>=_count)
197 {
198 _handler.onFrame(_more,_flags, _opcode, _buffer.get(_count));
199 _count=0;
200 _state=State.START;
201
202 if (_buffer.length()==0)
203 {
204 _buffers.returnBuffer(_buffer);
205 _buffer=null;
206 }
207
208 return total_filled;
209
210 }
211 }
212 }
213
214
215 public void fill(Buffer buffer)
216 {
217 if (buffer!=null && buffer.length()>0)
218 {
219 if (_buffer==null)
220 _buffer=_buffers.getBuffer();
221 _buffer.put(buffer);
222 buffer.clear();
223 }
224 }
225
226 }