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 }