1 module hunt.http.codec.http.decode.BodyParser;
2 
3 import hunt.http.codec.http.decode.HeaderParser;
4 import hunt.http.codec.http.decode.Parser;
5 import hunt.http.codec.http.decode.Parser;
6 import hunt.http.codec.http.frame;
7 
8 import hunt.io.BufferUtils;
9 import hunt.io.ByteBuffer;
10 
11 import hunt.logging;
12 
13 
14 
15 /**
16  * <p>
17  * The base parser for the frame body of HTTP/2 frames.
18  * </p>
19  * <p>
20  * Subclasses implement {@link #parse(ByteBuffer)} to parse the frame specific
21  * body.
22  * </p>
23  *
24  * @see Parser
25  */
26 abstract class BodyParser {
27     // 
28 
29     private HeaderParser headerParser;
30     private Parser.Listener listener;
31 
32     protected this(HeaderParser headerParser, Parser.Listener listener) {
33         this.headerParser = headerParser;
34         this.listener = listener;
35     }
36 
37     /**
38      * <p>
39      * Parses the body bytes in the given {@code buffer}; only the body bytes
40      * are consumed, therefore when this method returns, the buffer may contain
41      * unconsumed bytes.
42      * </p>
43      *
44      * @param buffer the buffer to parse
45      * @return true if the whole body bytes were parsed, false if not enough
46      * body bytes were present in the buffer
47      */
48     abstract bool parse(ByteBuffer buffer);
49 
50     void emptyBody(ByteBuffer buffer) {
51         connectionFailure(buffer, cast(int)ErrorCode.PROTOCOL_ERROR, "invalid_frame");
52     }
53 
54     protected bool hasFlag(int bit) {
55         return headerParser.hasFlag(bit);
56     }
57 
58     protected bool isPadding() {
59         return headerParser.hasFlag(Flags.PADDING);
60     }
61 
62     protected bool isEndStream() {
63         return headerParser.hasFlag(Flags.END_STREAM);
64     }
65 
66     protected int getStreamId() {
67         return headerParser.getStreamId();
68     }
69 
70     protected int getBodyLength() {
71         return headerParser.getLength();
72     }
73 
74     protected void notifyData(DataFrame frame) {
75         try {
76             listener.onData(frame);
77         } catch (Exception x) {
78             errorf("Failure while notifying listener %s", x, listener);
79         }
80     }
81 
82     protected void notifyHeaders(HeadersFrame frame) {
83         try {
84             listener.onHeaders(frame);
85         } catch (Exception x) {
86             errorf("Failure while notifying listener %s", x, listener);
87         }
88     }
89 
90     protected void notifyPriority(PriorityFrame frame) {
91         try {
92             listener.onPriority(frame);
93         } catch (Exception x) {
94             errorf("Failure while notifying listener %s", x, listener);
95         }
96     }
97 
98     protected void notifyReset(ResetFrame frame) {
99         try {
100             listener.onReset(frame);
101         } catch (Exception x) {
102             errorf("Failure while notifying listener %s", x, listener);
103         }
104     }
105 
106     protected void notifySettings(SettingsFrame frame) {
107         try {
108             listener.onSettings(frame);
109         } catch (Exception x) {
110             errorf("Failure while notifying listener %s", x, listener);
111         }
112     }
113 
114     protected void notifyPushPromise(PushPromiseFrame frame) {
115         try {
116             listener.onPushPromise(frame);
117         } catch (Exception x) {
118             errorf("Failure while notifying listener %s", x, listener);
119         }
120     }
121 
122     protected void notifyPing(PingFrame frame) {
123         try {
124             listener.onPing(frame);
125         } catch (Exception x) {
126             errorf("Failure while notifying listener %s", x, listener);
127         }
128     }
129 
130     protected void notifyGoAway(GoAwayFrame frame) {
131         try {
132             listener.onGoAway(frame);
133         } catch (Exception x) {
134             errorf("Failure while notifying listener %s", x, listener);
135         }
136     }
137 
138     protected void notifyWindowUpdate(WindowUpdateFrame frame) {
139         try {
140             listener.onWindowUpdate(frame);
141         } catch (Exception x) {
142             errorf("Failure while notifying listener %s", x, listener);
143         }
144     }
145 
146     protected bool connectionFailure(ByteBuffer buffer, int error, string reason) {
147         BufferUtils.clear(buffer);
148         notifyConnectionFailure(error, reason);
149         return false;
150     }
151 
152     private void notifyConnectionFailure(int error, string reason) {
153         try {
154             listener.onConnectionFailure(error, reason);
155         } catch (Exception x) {
156             errorf("Failure while notifying listener %s", x, listener);
157         }
158     }
159 }