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.Flags;
25 import org.eclipse.jetty.http2.frames.PingFrame;
26
27 public class PingBodyParser extends BodyParser
28 {
29 private State state = State.PREPARE;
30 private int cursor;
31 private byte[] payload;
32
33 public PingBodyParser(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 payload = null;
43 }
44
45 @Override
46 public boolean parse(ByteBuffer buffer)
47 {
48 while (buffer.hasRemaining())
49 {
50 switch (state)
51 {
52 case PREPARE:
53 {
54
55 if (getStreamId() != 0)
56 return connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_ping_frame");
57
58 if (getBodyLength() != 8)
59 return connectionFailure(buffer, ErrorCode.FRAME_SIZE_ERROR.code, "invalid_ping_frame");
60 state = State.PAYLOAD;
61 break;
62 }
63 case PAYLOAD:
64 {
65 payload = new byte[8];
66 if (buffer.remaining() >= 8)
67 {
68 buffer.get(payload);
69 return onPing(payload);
70 }
71 else
72 {
73 state = State.PAYLOAD_BYTES;
74 cursor = 8;
75 }
76 break;
77 }
78 case PAYLOAD_BYTES:
79 {
80 payload[8 - cursor] = buffer.get();
81 --cursor;
82 if (cursor == 0)
83 return onPing(payload);
84 break;
85 }
86 default:
87 {
88 throw new IllegalStateException();
89 }
90 }
91 }
92 return false;
93 }
94
95 private boolean onPing(byte[] payload)
96 {
97 PingFrame frame = new PingFrame(payload, hasFlag(Flags.ACK));
98 reset();
99 notifyPing(frame);
100 return true;
101 }
102
103 private enum State
104 {
105 PREPARE, PAYLOAD, PAYLOAD_BYTES
106 }
107 }