1 module hunt.http.codec.http.decode.WindowUpdateBodyParser; 2 3 import hunt.io.ByteBuffer; 4 5 import hunt.http.codec.http.decode.BodyParser; 6 import hunt.http.codec.http.decode.HeaderParser; 7 import hunt.http.codec.http.decode.Parser; 8 9 import hunt.http.codec.http.frame.ErrorCode; 10 import hunt.http.codec.http.frame.WindowUpdateFrame; 11 12 import hunt.Exceptions; 13 14 /** 15 */ 16 class WindowUpdateBodyParser :BodyParser { 17 private State state = State.PREPARE; 18 private int cursor; 19 private int windowDelta; 20 21 this(HeaderParser headerParser, Parser.Listener listener) { 22 super(headerParser, listener); 23 } 24 25 private void reset() { 26 state = State.PREPARE; 27 cursor = 0; 28 windowDelta = 0; 29 } 30 31 override 32 bool parse(ByteBuffer buffer) { 33 while (buffer.hasRemaining()) { 34 switch (state) { 35 case State.PREPARE: { 36 int length = getBodyLength(); 37 if (length != 4) 38 return connectionFailure(buffer, cast(int)ErrorCode.FRAME_SIZE_ERROR, "invalid_window_update_frame"); 39 state = State.WINDOW_DELTA; 40 break; 41 } 42 case State.WINDOW_DELTA: { 43 if (buffer.remaining() >= 4) { 44 windowDelta = buffer.get!int() & 0x7F_FF_FF_FF; 45 return onWindowUpdate(windowDelta); 46 } else { 47 state = State.WINDOW_DELTA_BYTES; 48 cursor = 4; 49 } 50 break; 51 } 52 case State.WINDOW_DELTA_BYTES: { 53 byte currByte = buffer.get(); 54 --cursor; 55 windowDelta += (currByte & 0xFF) << 8 * cursor; 56 if (cursor == 0) { 57 windowDelta &= 0x7F_FF_FF_FF; 58 return onWindowUpdate(windowDelta); 59 } 60 break; 61 } 62 default: { 63 throw new IllegalStateException(""); 64 } 65 } 66 } 67 return false; 68 } 69 70 private bool onWindowUpdate(int windowDelta) { 71 WindowUpdateFrame frame = new WindowUpdateFrame(getStreamId(), windowDelta); 72 reset(); 73 notifyWindowUpdate(frame); 74 return true; 75 } 76 77 private enum State { 78 PREPARE, WINDOW_DELTA, WINDOW_DELTA_BYTES 79 } 80 }