1 module hunt.http.codec.http.decode.HeaderParser; 2 3 import hunt.io.ByteBuffer; 4 5 import hunt.http.codec.http.frame.Frame; 6 7 import hunt.Exceptions; 8 9 /** 10 * <p> 11 * The parser for the frame header of HTTP/2 frames. 12 * </p> 13 * 14 * @see Parser 15 */ 16 class HeaderParser { 17 private State state = State.LENGTH; 18 private int cursor; 19 20 private int length; 21 private int type; 22 private int flags; 23 private int streamId; 24 25 void reset() { 26 state = State.LENGTH; 27 cursor = 0; 28 29 length = 0; 30 type = 0; 31 flags = 0; 32 streamId = 0; 33 } 34 35 /** 36 * <p> 37 * Parses the header bytes in the given {@code buffer}; only the header 38 * bytes are consumed, therefore when this method returns, the buffer may 39 * contain unconsumed bytes. 40 * </p> 41 * 42 * @param buffer 43 * the buffer to parse 44 * @return true if the whole header bytes were parsed, false if not enough 45 * header bytes were present in the buffer 46 */ 47 bool parse(ByteBuffer buffer) { 48 while (buffer.hasRemaining()) { 49 switch (state) { 50 case State.LENGTH: { 51 int octet = buffer.get() & 0xFF; 52 length = (length << 8) + octet; 53 if (++cursor == 3) { 54 length &= Frame.MAX_MAX_LENGTH; 55 state = State.TYPE; 56 } 57 break; 58 } 59 case State.TYPE: { 60 type = buffer.get() & 0xFF; 61 state = State.FLAGS; 62 break; 63 } 64 case State.FLAGS: { 65 flags = buffer.get() & 0xFF; 66 state = State.STREAM_ID; 67 break; 68 } 69 case State.STREAM_ID: { 70 if (buffer.remaining() >= 4) { 71 streamId = buffer.get!int(); 72 // Most significant bit MUST be ignored as per specification. 73 streamId &= 0x7F_FF_FF_FF; 74 return true; 75 } else { 76 state = State.STREAM_ID_BYTES; 77 cursor = 4; 78 } 79 break; 80 } 81 case State.STREAM_ID_BYTES: { 82 int currByte = buffer.get() & 0xFF; 83 --cursor; 84 streamId += currByte << (8 * cursor); 85 if (cursor == 0) { 86 // Most significant bit MUST be ignored as per specification. 87 streamId &= 0x7F_FF_FF_FF; 88 return true; 89 } 90 break; 91 } 92 default: { 93 throw new IllegalStateException(""); 94 } 95 } 96 } 97 return false; 98 } 99 100 int getLength() { 101 return length; 102 } 103 104 int getFrameType() { 105 return type; 106 } 107 108 bool hasFlag(int bit) { 109 return (flags & bit) == bit; 110 } 111 112 int getStreamId() { 113 return streamId; 114 } 115 116 private enum State { 117 LENGTH, TYPE, FLAGS, STREAM_ID, STREAM_ID_BYTES 118 } 119 }