1 /** @file
2 
3   Http2Frame
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22  */
23 
24 #pragma once
25 
26 #include "P_Net.h"
27 
28 #include "HTTP2.h"
29 
30 /**
31    Incoming HTTP/2 Frame
32  */
33 class Http2Frame
34 {
35 public:
_hdr(h)36   Http2Frame(const Http2FrameHeader &h, IOBufferReader *r, bool e = false) : _hdr(h), _ioreader(r), _from_early_data(e) {}
37 
38   // Accessor
39   IOBufferReader *reader() const;
40   const Http2FrameHeader &header() const;
41   bool is_from_early_data() const;
42 
43 private:
44   Http2FrameHeader _hdr;
45   IOBufferReader *_ioreader = nullptr;
46   bool _from_early_data     = false;
47 };
48 
49 /**
50    Outgoing HTTP/2 Frame
51  */
52 class Http2TxFrame
53 {
54 public:
Http2TxFrame(const Http2FrameHeader & h)55   Http2TxFrame(const Http2FrameHeader &h) : _hdr(h) {}
~Http2TxFrame()56   virtual ~Http2TxFrame() {}
57 
58   // Don't allocate on heap
59   void *operator new(std::size_t)   = delete;
60   void *operator new[](std::size_t) = delete;
61 
62   virtual int64_t write_to(MIOBuffer *iobuffer) const = 0;
63 
64 protected:
65   Http2FrameHeader _hdr;
66 };
67 
68 /**
69    DATA Frame
70  */
71 class Http2DataFrame : public Http2TxFrame
72 {
73 public:
Http2DataFrame(Http2StreamId stream_id,uint8_t flags,IOBufferReader * r,uint32_t l)74   Http2DataFrame(Http2StreamId stream_id, uint8_t flags, IOBufferReader *r, uint32_t l)
75     : Http2TxFrame({l, HTTP2_FRAME_TYPE_DATA, flags, stream_id}), _reader(r), _payload_len(l)
76   {
77   }
78 
79   int64_t write_to(MIOBuffer *iobuffer) const override;
80 
81 private:
82   IOBufferReader *_reader = nullptr;
83   uint32_t _payload_len   = 0;
84 };
85 
86 /**
87    HEADERS Frame
88 
89    TODO: support priority info & padding using Http2HeadersParameter
90  */
91 class Http2HeadersFrame : public Http2TxFrame
92 {
93 public:
Http2HeadersFrame(Http2StreamId stream_id,uint8_t flags,uint8_t * h,uint32_t l)94   Http2HeadersFrame(Http2StreamId stream_id, uint8_t flags, uint8_t *h, uint32_t l)
95     : Http2TxFrame({l, HTTP2_FRAME_TYPE_HEADERS, flags, stream_id}), _hdr_block(h), _hdr_block_len(l)
96   {
97   }
98 
99   int64_t write_to(MIOBuffer *iobuffer) const override;
100 
101 private:
102   uint8_t *_hdr_block     = nullptr;
103   uint32_t _hdr_block_len = 0;
104 };
105 
106 /**
107    PRIORITY Frame
108 
109    TODO: implement xmit function
110  */
111 class Http2PriorityFrame : public Http2TxFrame
112 {
113 public:
Http2PriorityFrame(Http2StreamId stream_id,uint8_t flags,Http2Priority p)114   Http2PriorityFrame(Http2StreamId stream_id, uint8_t flags, Http2Priority p)
115     : Http2TxFrame({HTTP2_PRIORITY_LEN, HTTP2_FRAME_TYPE_PRIORITY, flags, stream_id}), _params(p)
116   {
117   }
118 
119   int64_t write_to(MIOBuffer *iobuffer) const override;
120 
121 private:
122   Http2Priority _params;
123 };
124 
125 /**
126    RST_STREAM Frame
127  */
128 class Http2RstStreamFrame : public Http2TxFrame
129 {
130 public:
Http2RstStreamFrame(Http2StreamId stream_id,uint32_t e)131   Http2RstStreamFrame(Http2StreamId stream_id, uint32_t e)
132     : Http2TxFrame({HTTP2_RST_STREAM_LEN, HTTP2_FRAME_TYPE_RST_STREAM, HTTP2_FRAME_NO_FLAG, stream_id}), _error_code(e)
133   {
134   }
135 
136   int64_t write_to(MIOBuffer *iobuffer) const override;
137 
138 private:
139   uint32_t _error_code;
140 };
141 
142 /**
143    SETTINGS Frame
144  */
145 class Http2SettingsFrame : public Http2TxFrame
146 {
147 public:
Http2SettingsFrame(Http2StreamId stream_id,uint8_t flags)148   Http2SettingsFrame(Http2StreamId stream_id, uint8_t flags) : Http2TxFrame({0, HTTP2_FRAME_TYPE_SETTINGS, flags, stream_id}) {}
Http2SettingsFrame(Http2StreamId stream_id,uint8_t flags,Http2SettingsParameter * p,uint32_t s)149   Http2SettingsFrame(Http2StreamId stream_id, uint8_t flags, Http2SettingsParameter *p, uint32_t s)
150     : Http2TxFrame({static_cast<uint32_t>(HTTP2_SETTINGS_PARAMETER_LEN) * s, HTTP2_FRAME_TYPE_SETTINGS, flags, stream_id}),
151       _params(p),
152       _psize(s)
153   {
154   }
155 
156   int64_t write_to(MIOBuffer *iobuffer) const override;
157 
158 private:
159   Http2SettingsParameter *_params = nullptr;
160   uint32_t _psize                 = 0;
161 };
162 
163 /**
164    PUSH_PROMISE Frame
165 
166    TODO: support padding
167  */
168 class Http2PushPromiseFrame : public Http2TxFrame
169 {
170 public:
Http2PushPromiseFrame(Http2StreamId stream_id,uint8_t flags,Http2PushPromise p,uint8_t * h,uint32_t l)171   Http2PushPromiseFrame(Http2StreamId stream_id, uint8_t flags, Http2PushPromise p, uint8_t *h, uint32_t l)
172     : Http2TxFrame({l + static_cast<uint32_t>(sizeof(Http2StreamId)), HTTP2_FRAME_TYPE_PUSH_PROMISE, flags, stream_id}),
173       _params(p),
174       _hdr_block(h),
175       _hdr_block_len(l)
176   {
177   }
178 
179   int64_t write_to(MIOBuffer *iobuffer) const override;
180 
181 private:
182   Http2PushPromise _params;
183   uint8_t *_hdr_block     = nullptr;
184   uint32_t _hdr_block_len = 0;
185 };
186 
187 /**
188    PING Frame
189  */
190 class Http2PingFrame : public Http2TxFrame
191 {
192 public:
Http2PingFrame(Http2StreamId stream_id,uint8_t flags,const uint8_t * data)193   Http2PingFrame(Http2StreamId stream_id, uint8_t flags, const uint8_t *data)
194     : Http2TxFrame({HTTP2_PING_LEN, HTTP2_FRAME_TYPE_PING, flags, stream_id}), _opaque_data(data)
195   {
196   }
197 
198   int64_t write_to(MIOBuffer *iobuffer) const override;
199 
200 private:
201   const uint8_t *_opaque_data;
202 };
203 
204 /**
205    GOAWAY Frame
206 
207    TODO: support Additional Debug Data
208  */
209 class Http2GoawayFrame : public Http2TxFrame
210 {
211 public:
Http2GoawayFrame(Http2Goaway p)212   Http2GoawayFrame(Http2Goaway p)
213     : Http2TxFrame({HTTP2_GOAWAY_LEN, HTTP2_FRAME_TYPE_GOAWAY, HTTP2_FRAME_NO_FLAG, HTTP2_CONNECTION_CONTROL_STRTEAM}), _params(p)
214   {
215   }
216 
217   int64_t write_to(MIOBuffer *iobuffer) const override;
218 
219 private:
220   Http2Goaway _params;
221 };
222 
223 /**
224    WINDOW_UPDATE Frame
225  */
226 class Http2WindowUpdateFrame : public Http2TxFrame
227 {
228 public:
Http2WindowUpdateFrame(Http2StreamId stream_id,uint32_t w)229   Http2WindowUpdateFrame(Http2StreamId stream_id, uint32_t w)
230     : Http2TxFrame({HTTP2_WINDOW_UPDATE_LEN, HTTP2_FRAME_TYPE_WINDOW_UPDATE, HTTP2_FRAME_NO_FLAG, stream_id}), _window(w)
231   {
232   }
233 
234   int64_t write_to(MIOBuffer *iobuffer) const override;
235 
236 private:
237   uint32_t _window = 0;
238 };
239 
240 /**
241    CONTINUATION Frame
242  */
243 class Http2ContinuationFrame : public Http2TxFrame
244 {
245 public:
Http2ContinuationFrame(Http2StreamId stream_id,uint8_t flags,uint8_t * h,uint32_t l)246   Http2ContinuationFrame(Http2StreamId stream_id, uint8_t flags, uint8_t *h, uint32_t l)
247     : Http2TxFrame({l, HTTP2_FRAME_TYPE_CONTINUATION, flags, stream_id}), _hdr_block(h), _hdr_block_len(l)
248   {
249   }
250 
251   int64_t write_to(MIOBuffer *iobuffer) const override;
252 
253 private:
254   uint8_t *_hdr_block     = nullptr;
255   uint32_t _hdr_block_len = 0;
256 };
257