1 module hunt.http.codec.http.decode.ServerParser;
2 
3 
4 import hunt.http.codec.http.decode.PrefaceParser;
5 import hunt.http.codec.http.decode.Parser;
6 import hunt.http.codec.http.frame.ErrorCode;
7 import hunt.http.codec.http.frame.Flags;
8 import hunt.http.codec.http.frame.FrameType;
9 
10 import hunt.io.ByteBuffer;
11 import hunt.io.BufferUtils;
12 
13 import hunt.logging;
14 import hunt.Exceptions;
15 
16 
17 /**
18 */
19 class ServerParser :Parser {
20 
21 	private Listener listener;
22 	private PrefaceParser prefaceParser;
23 	private State state = State.PREFACE;
24 	private bool _notifyPreface = true;
25 
26 	this(Listener listener, int maxDynamicTableSize, int maxHeaderSize) {
27 		super(listener, maxDynamicTableSize, maxHeaderSize);
28 		this.listener = listener;
29 		this.prefaceParser = new PrefaceParser(listener);
30 	}
31 
32 	/**
33 	 * <p>
34 	 * A direct upgrade is an unofficial upgrade from HTTP/1.1 to HTTP/2.0.
35 	 * </p>
36 	 * <p>
37 	 * A direct upgrade is initiated when
38 	 * HTTP connection sees a request with these
39 	 * bytes:
40 	 * </p>
41 	 * 
42 	 * <pre>
43 	 * PRI * HTTP/2.0\r\n
44 	 * \r\n
45 	 * </pre>
46 	 * <p>
47 	 * This request is part of the HTTP/2.0 preface, indicating that a HTTP/2.0
48 	 * client is attempting a h2c direct connection.
49 	 * </p>
50 	 * <p>
51 	 * This is not a standard HTTP/1.1 Upgrade path.
52 	 * </p>
53 	 */
54 	void directUpgrade() {
55 		if (state != State.PREFACE)
56 			throw new IllegalStateException("");
57 		prefaceParser.directUpgrade();
58 	}
59 
60 	/**
61 	 * <p>
62 	 * The standard HTTP/1.1 upgrade path.
63 	 * </p>
64 	 */
65 	void standardUpgrade() {
66 		if (state != State.PREFACE)
67 			throw new IllegalStateException("");
68 		_notifyPreface = false;
69 	}
70 
71 	override
72 	void parse(ByteBuffer buffer) {
73 		version(HuntDebutMode)
74 		tracef("parsing buffer: %s", buffer.toString());
75 		try {
76 			while (true) {
77 				switch (state) {
78 				case State.PREFACE: {
79 					if (prefaceParser.parse(buffer)) {
80 						if (_notifyPreface) {
81 							onPreface();
82 						}
83 						state = State.SETTINGS;
84 						break;
85 					} else {
86 						return;
87 					}
88 				}
89 				case State.SETTINGS: {
90 					if (parseHeader(buffer)) {
91 						if (getFrameType() != FrameType.SETTINGS || hasFlag(Flags.ACK)) {
92 							buffer.clear();
93 							notifyConnectionFailure(cast(int)ErrorCode.PROTOCOL_ERROR, "invalid_preface");
94 							return;
95 						}
96 						if (parseBody(buffer)) {
97 							state = State.FRAMES;
98 							break;
99 						} else {
100 							return;
101 						}
102 					} else {
103 						return;
104 					}
105 				}
106 				case State.FRAMES: {
107 					// Stay forever in the FRAMES state.
108 					super.parse(buffer);
109 					return;
110 				}
111 				default: {
112 					throw new IllegalStateException("");
113 				}
114 				}
115 			}
116 		} catch (Exception x) {
117 			errorf("server parser error", x);
118 			BufferUtils.clear(buffer);
119 			notifyConnectionFailure(cast(int)ErrorCode.PROTOCOL_ERROR, "parser_error");
120 		}
121 	}
122 
123 	protected void onPreface() {
124 		notifyPreface();
125 	}
126 
127 	private void notifyPreface() {
128 		try {
129 			listener.onPreface();
130 		} catch (Exception x) {
131 			errorf("Failure while notifying listener %s", x.message);
132 		}
133 	}
134 
135 	interface Listener : Parser.Listener {
136 		void onPreface();
137 
138 		class Adapter : Parser.Listener.Adapter, Listener {
139 			override
140 			void onPreface() {
141 			}
142 		}
143 	}
144 
145 	private enum State {
146 		PREFACE, SETTINGS, FRAMES
147 	}
148 }