1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http2.parser;
20
21 import java.nio.ByteBuffer;
22
23 import org.eclipse.jetty.http2.ErrorCode;
24 import org.eclipse.jetty.http2.frames.PriorityFrame;
25
26 public class PriorityBodyParser extends BodyParser
27 {
28 private State state = State.PREPARE;
29 private int cursor;
30 private boolean exclusive;
31 private int parentStreamId;
32
33 public PriorityBodyParser(HeaderParser headerParser, Parser.Listener listener)
34 {
35 super(headerParser, listener);
36 }
37
38 private void reset()
39 {
40 state = State.PREPARE;
41 cursor = 0;
42 exclusive = false;
43 parentStreamId = 0;
44 }
45
46 @Override
47 public boolean parse(ByteBuffer buffer)
48 {
49 while (buffer.hasRemaining())
50 {
51 switch (state)
52 {
53 case PREPARE:
54 {
55
56 if (getStreamId() == 0)
57 return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_priority_frame");
58 int length = getBodyLength();
59 if (length != 5)
60 return connectionFailure(buffer, ErrorCode.FRAME_SIZE_ERROR.code, "invalid_priority_frame");
61 state = State.EXCLUSIVE;
62 break;
63 }
64 case EXCLUSIVE:
65 {
66
67
68 int currByte = buffer.get(buffer.position());
69 exclusive = (currByte & 0x80) == 0x80;
70 state = State.PARENT_STREAM_ID;
71 break;
72 }
73 case PARENT_STREAM_ID:
74 {
75 if (buffer.remaining() >= 4)
76 {
77 parentStreamId = buffer.getInt();
78 parentStreamId &= 0x7F_FF_FF_FF;
79 state = State.WEIGHT;
80 }
81 else
82 {
83 state = State.PARENT_STREAM_ID_BYTES;
84 cursor = 4;
85 }
86 break;
87 }
88 case PARENT_STREAM_ID_BYTES:
89 {
90 int currByte = buffer.get() & 0xFF;
91 --cursor;
92 parentStreamId += currByte << (8 * cursor);
93 if (cursor == 0)
94 {
95 parentStreamId &= 0x7F_FF_FF_FF;
96 state = State.WEIGHT;
97 }
98 break;
99 }
100 case WEIGHT:
101 {
102
103 if (getStreamId() == parentStreamId)
104 return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_priority_frame");
105
106 int weight = (buffer.get() & 0xFF) + 1;
107 return onPriority(parentStreamId, weight, exclusive);
108 }
109 default:
110 {
111 throw new IllegalStateException();
112 }
113 }
114 }
115 return false;
116 }
117
118 private boolean onPriority(int parentStreamId, int weight, boolean exclusive)
119 {
120 PriorityFrame frame = new PriorityFrame(getStreamId(), parentStreamId, weight, exclusive);
121 reset();
122 notifyPriority(frame);
123 return true;
124 }
125
126 private enum State
127 {
128 PREPARE, EXCLUSIVE, PARENT_STREAM_ID, PARENT_STREAM_ID_BYTES, WEIGHT
129 }
130 }