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.DataInfo;
24 import org.eclipse.jetty.spdy.frames.DataFrame;
25
26 public abstract class DataFrameParser
27 {
28 private State state = State.STREAM_ID;
29 private int cursor;
30 private int streamId;
31 private byte flags;
32 private int length;
33
34
35
36
37
38
39
40 public boolean parse(ByteBuffer buffer)
41 {
42 while (buffer.hasRemaining())
43 {
44 switch (state)
45 {
46 case STREAM_ID:
47 {
48 if (buffer.remaining() >= 4)
49 {
50 streamId = buffer.getInt() & 0x7F_FF_FF_FF;
51 state = State.FLAGS;
52 }
53 else
54 {
55 state = State.STREAM_ID_BYTES;
56 cursor = 4;
57 }
58 break;
59 }
60 case STREAM_ID_BYTES:
61 {
62 byte currByte = buffer.get();
63 --cursor;
64 streamId += (currByte & 0xFF) << 8 * cursor;
65 if (cursor == 0)
66 state = State.FLAGS;
67 break;
68 }
69 case FLAGS:
70 {
71 flags = buffer.get();
72 cursor = 3;
73 state = State.LENGTH;
74 break;
75 }
76 case LENGTH:
77 {
78 byte currByte = buffer.get();
79 --cursor;
80 length += (currByte & 0xFF) << 8 * cursor;
81 if (cursor > 0)
82 break;
83 state = State.DATA;
84
85
86 if (length > 0)
87 break;
88 }
89 case DATA:
90 {
91
92
93
94
95
96
97 int size = Math.min(length, buffer.remaining());
98 int limit = buffer.limit();
99 buffer.limit(buffer.position() + size);
100 ByteBuffer bytes = buffer.slice();
101 buffer.limit(limit);
102 buffer.position(buffer.position() + size);
103 length -= size;
104 if (length == 0)
105 {
106 onDataFrame(bytes);
107 return true;
108 }
109 else
110 {
111
112
113 onDataFragment(bytes);
114 }
115 break;
116 }
117 default:
118 {
119 throw new IllegalStateException();
120 }
121 }
122 }
123 return false;
124 }
125
126 private void onDataFrame(ByteBuffer bytes)
127 {
128 DataFrame frame = new DataFrame(streamId, flags, bytes.remaining());
129 onDataFrame(frame, bytes);
130 reset();
131 }
132
133 private void onDataFragment(ByteBuffer bytes)
134 {
135 DataFrame frame = new DataFrame(streamId, (byte)(flags & ~DataInfo.FLAG_CLOSE), bytes.remaining());
136 onDataFrame(frame, bytes);
137
138 }
139
140 protected abstract void onDataFrame(DataFrame frame, ByteBuffer data);
141
142 private void reset()
143 {
144 state = State.STREAM_ID;
145 cursor = 0;
146 streamId = 0;
147 flags = 0;
148 length = 0;
149 }
150
151 private enum State
152 {
153 STREAM_ID, STREAM_ID_BYTES, FLAGS, LENGTH, DATA
154 }
155 }