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 }