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