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
23 import org.eclipse.jetty.spdy.api.SPDY;
24 import org.eclipse.jetty.spdy.api.Settings;
25 import org.eclipse.jetty.spdy.frames.SettingsFrame;
26
27 public class SettingsBodyParser extends ControlFrameBodyParser
28 {
29 private final Settings settings = new Settings();
30 private final ControlFrameParser controlFrameParser;
31 private State state = State.COUNT;
32 private int cursor;
33 private int count;
34 private int idAndFlags;
35 private int value;
36
37 public SettingsBodyParser(ControlFrameParser controlFrameParser)
38 {
39 this.controlFrameParser = controlFrameParser;
40 }
41
42 @Override
43 public boolean parse(ByteBuffer buffer)
44 {
45 while (buffer.hasRemaining())
46 {
47 switch (state)
48 {
49 case COUNT:
50 {
51 if (buffer.remaining() >= 4)
52 {
53 count = buffer.getInt();
54 state = State.ID_FLAGS;
55 }
56 else
57 {
58 state = State.COUNT_BYTES;
59 cursor = 4;
60 }
61 break;
62 }
63 case COUNT_BYTES:
64 {
65 byte currByte = buffer.get();
66 --cursor;
67 count += (currByte & 0xFF) << 8 * cursor;
68 if (cursor == 0)
69 state = State.ID_FLAGS;
70 break;
71 }
72 case ID_FLAGS:
73 {
74 if (buffer.remaining() >= 4)
75 {
76 idAndFlags = convertIdAndFlags(controlFrameParser.getVersion(), buffer.getInt());
77 state = State.VALUE;
78 }
79 else
80 {
81 state = State.ID_FLAGS_BYTES;
82 cursor = 4;
83 }
84 break;
85 }
86 case ID_FLAGS_BYTES:
87 {
88 byte currByte = buffer.get();
89 --cursor;
90 value += (currByte & 0xFF) << 8 * cursor;
91 if (cursor == 0)
92 {
93 idAndFlags = convertIdAndFlags(controlFrameParser.getVersion(), value);
94 state = State.VALUE;
95 }
96 break;
97 }
98 case VALUE:
99 {
100 if (buffer.remaining() >= 4)
101 {
102 value = buffer.getInt();
103 if (onPair())
104 return true;
105 }
106 else
107 {
108 state = State.VALUE_BYTES;
109 cursor = 4;
110 value = 0;
111 }
112 break;
113 }
114 case VALUE_BYTES:
115 {
116 byte currByte = buffer.get();
117 --cursor;
118 value += (currByte & 0xFF) << 8 * cursor;
119 if (cursor == 0)
120 {
121 if (onPair())
122 return true;
123 }
124 break;
125 }
126 default:
127 {
128 throw new IllegalStateException();
129 }
130 }
131 }
132 return false;
133 }
134
135 private int convertIdAndFlags(short version, int idAndFlags)
136 {
137 switch (version)
138 {
139 case SPDY.V2:
140 {
141
142
143
144
145 int result = (idAndFlags & 0x00_00_00_FF) << 24;
146 result += (idAndFlags & 0x00_00_FF_00) << 8;
147 result += (idAndFlags & 0x00_FF_00_00) >>> 8;
148 result += (idAndFlags & 0xFF_00_00_00) >>> 24;
149 return result;
150 }
151 case SPDY.V3:
152 {
153 return idAndFlags;
154 }
155 default:
156 {
157 throw new IllegalStateException();
158 }
159 }
160 }
161
162 private boolean onPair()
163 {
164 int id = idAndFlags & 0x00_FF_FF_FF;
165 byte flags = (byte)((idAndFlags & 0xFF_00_00_00) >>> 24);
166 settings.put(new Settings.Setting(Settings.ID.from(id), Settings.Flag.from(flags), value));
167 state = State.ID_FLAGS;
168 idAndFlags = 0;
169 value = 0;
170 --count;
171 if (count == 0)
172 {
173 onSettings();
174 return true;
175 }
176 return false;
177 }
178
179 private void onSettings()
180 {
181 SettingsFrame frame = new SettingsFrame(controlFrameParser.getVersion(), controlFrameParser.getFlags(), new Settings(settings, true));
182 controlFrameParser.onControlFrame(frame);
183 reset();
184 }
185
186 private void reset()
187 {
188 settings.clear();
189 state = State.COUNT;
190 cursor = 0;
191 count = 0;
192 idAndFlags = 0;
193 value = 0;
194 }
195
196 private enum State
197 {
198 COUNT, COUNT_BYTES, ID_FLAGS, ID_FLAGS_BYTES, VALUE, VALUE_BYTES
199 }
200 }