1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.spdy.parser;
20
21 import java.nio.ByteBuffer;
22 import java.util.EventListener;
23 import java.util.List;
24 import java.util.concurrent.CopyOnWriteArrayList;
25
26 import org.eclipse.jetty.spdy.CompressionFactory;
27 import org.eclipse.jetty.spdy.SessionException;
28 import org.eclipse.jetty.spdy.StreamException;
29 import org.eclipse.jetty.spdy.api.SessionStatus;
30 import org.eclipse.jetty.spdy.frames.ControlFrame;
31 import org.eclipse.jetty.spdy.frames.DataFrame;
32 import org.eclipse.jetty.util.log.Log;
33 import org.eclipse.jetty.util.log.Logger;
34
35 public class Parser
36 {
37 private static final Logger logger = Log.getLogger(Parser.class);
38 private final List<Listener> listeners = new CopyOnWriteArrayList<>();
39 private final ControlFrameParser controlFrameParser;
40 private final DataFrameParser dataFrameParser;
41 private State state = State.CONTROL_BIT;
42
43 public Parser(CompressionFactory.Decompressor decompressor)
44 {
45
46
47 controlFrameParser = new ControlFrameParser(decompressor)
48 {
49 @Override
50 protected void onControlFrame(ControlFrame frame)
51 {
52 logger.debug("Parsed {}", frame);
53 notifyControlFrame(frame);
54 }
55 };
56 dataFrameParser = new DataFrameParser()
57 {
58 @Override
59 protected void onDataFrame(DataFrame frame, ByteBuffer data)
60 {
61 logger.debug("Parsed {}, {} data bytes", frame, data.remaining());
62 notifyDataFrame(frame, data);
63 }
64 };
65 }
66
67 public void addListener(Listener listener)
68 {
69 listeners.add(listener);
70 }
71
72 public void removeListener(Listener listener)
73 {
74 listeners.remove(listener);
75 }
76
77 protected void notifyControlFrame(ControlFrame frame)
78 {
79 for (Listener listener : listeners)
80 {
81 try
82 {
83 listener.onControlFrame(frame);
84 }
85 catch (Exception x)
86 {
87 logger.info("Exception while notifying listener " + listener, x);
88 }
89 }
90 }
91
92 protected void notifyDataFrame(DataFrame frame, ByteBuffer data)
93 {
94 for (Listener listener : listeners)
95 {
96 try
97 {
98 listener.onDataFrame(frame, data);
99 }
100 catch (Exception x)
101 {
102 logger.info("Exception while notifying listener " + listener, x);
103 }
104 }
105 }
106
107 protected void notifyStreamException(StreamException x)
108 {
109 for (Listener listener : listeners)
110 {
111 try
112 {
113 listener.onStreamException(x);
114 }
115 catch (Exception xx)
116 {
117 logger.debug("Could not notify listener " + listener, xx);
118 }
119 }
120 }
121
122 protected void notifySessionException(SessionException x)
123 {
124 logger.debug("SPDY session exception", x);
125 for (Listener listener : listeners)
126 {
127 try
128 {
129 listener.onSessionException(x);
130 }
131 catch (Exception xx)
132 {
133 logger.debug("Could not notify listener " + listener, xx);
134 }
135 }
136 }
137
138 public void parse(ByteBuffer buffer)
139 {
140 logger.debug("Parsing {} bytes", buffer.remaining());
141 try
142 {
143 while (buffer.hasRemaining())
144 {
145 try
146 {
147 switch (state)
148 {
149 case CONTROL_BIT:
150 {
151
152
153 int currByte = buffer.get(buffer.position());
154 boolean isControlFrame = (currByte & 0x80) == 0x80;
155 state = isControlFrame ? State.CONTROL_FRAME : State.DATA_FRAME;
156 break;
157 }
158 case CONTROL_FRAME:
159 {
160 if (controlFrameParser.parse(buffer))
161 reset();
162 break;
163 }
164 case DATA_FRAME:
165 {
166 if (dataFrameParser.parse(buffer))
167 reset();
168 break;
169 }
170 default:
171 {
172 throw new IllegalStateException();
173 }
174 }
175 }
176 catch (StreamException x)
177 {
178 notifyStreamException(x);
179 }
180 }
181 }
182 catch (SessionException x)
183 {
184 notifySessionException(x);
185 }
186 catch (Throwable x)
187 {
188 notifySessionException(new SessionException(SessionStatus.PROTOCOL_ERROR, x));
189 }
190 finally
191 {
192
193 buffer.position(buffer.limit());
194 }
195 }
196
197 private void reset()
198 {
199 state = State.CONTROL_BIT;
200 }
201
202 public interface Listener extends EventListener
203 {
204 public void onControlFrame(ControlFrame frame);
205
206 public void onDataFrame(DataFrame frame, ByteBuffer data);
207
208 public void onStreamException(StreamException x);
209
210 public void onSessionException(SessionException x);
211
212 public static class Adapter implements Listener
213 {
214 @Override
215 public void onControlFrame(ControlFrame frame)
216 {
217 }
218
219 @Override
220 public void onDataFrame(DataFrame frame, ByteBuffer data)
221 {
222 }
223
224 @Override
225 public void onStreamException(StreamException x)
226 {
227 }
228
229 @Override
230 public void onSessionException(SessionException x)
231 {
232 }
233 }
234 }
235
236 private enum State
237 {
238 CONTROL_BIT, CONTROL_FRAME, DATA_FRAME
239 }
240 }