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