1 /** @file
2 
3   Http2ConnectionState.
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 #include "P_Net.h"
25 #include "Http2ConnectionState.h"
26 #include "Http2ClientSession.h"
27 #include "Http2Stream.h"
28 #include "Http2Frame.h"
29 #include "Http2DebugNames.h"
30 #include "HttpDebugNames.h"
31 
32 #include "tscpp/util/PostScript.h"
33 
34 #include <sstream>
35 #include <numeric>
36 
37 #define REMEMBER(e, r)                                        \
38   {                                                           \
39     if (this->ua_session) {                                   \
40       this->ua_session->remember(MakeSourceLocation(), e, r); \
41     }                                                         \
42   }
43 
44 #define Http2ConDebug(ua_session, fmt, ...) \
45   SsnDebug(ua_session, "http2_con", "[%" PRId64 "] " fmt, ua_session->connection_id(), ##__VA_ARGS__);
46 
47 #define Http2StreamDebug(ua_session, stream_id, fmt, ...) \
48   SsnDebug(ua_session, "http2_con", "[%" PRId64 "] [%u] " fmt, ua_session->connection_id(), stream_id, ##__VA_ARGS__);
49 
50 using http2_frame_dispatch = Http2Error (*)(Http2ConnectionState &, const Http2Frame &);
51 
52 static const int buffer_size_index[HTTP2_FRAME_TYPE_MAX] = {
53   BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_DATA
54   BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_HEADERS
55   -1,                    // HTTP2_FRAME_TYPE_PRIORITY
56   -1,                    // HTTP2_FRAME_TYPE_RST_STREAM
57   -1,                    // HTTP2_FRAME_TYPE_SETTINGS
58   BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_PUSH_PROMISE
59   -1,                    // HTTP2_FRAME_TYPE_PING
60   -1,                    // HTTP2_FRAME_TYPE_GOAWAY
61   -1,                    // HTTP2_FRAME_TYPE_WINDOW_UPDATE
62   BUFFER_SIZE_INDEX_16K, // HTTP2_FRAME_TYPE_CONTINUATION
63 };
64 
65 inline static unsigned
read_rcv_buffer(char * buf,size_t bufsize,unsigned & nbytes,const Http2Frame & frame)66 read_rcv_buffer(char *buf, size_t bufsize, unsigned &nbytes, const Http2Frame &frame)
67 {
68   char *end;
69 
70   if (frame.header().length - nbytes > bufsize) {
71     end = frame.reader()->memcpy(buf, bufsize, nbytes);
72   } else {
73     end = frame.reader()->memcpy(buf, frame.header().length - nbytes, nbytes);
74   }
75   nbytes += end - buf;
76 
77   return end - buf;
78 }
79 
80 static Http2Error
rcv_data_frame(Http2ConnectionState & cstate,const Http2Frame & frame)81 rcv_data_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
82 {
83   unsigned nbytes               = 0;
84   Http2StreamId id              = frame.header().streamid;
85   uint8_t pad_length            = 0;
86   const uint32_t payload_length = frame.header().length;
87 
88   Http2StreamDebug(cstate.ua_session, id, "Received DATA frame");
89 
90   if (cstate.get_zombie_event()) {
91     Warning("Data frame for zombied session %" PRId64, cstate.ua_session->connection_id());
92   }
93 
94   // If a DATA frame is received whose stream identifier field is 0x0, the
95   // recipient MUST
96   // respond with a connection error of type PROTOCOL_ERROR.
97   if (!http2_is_client_streamid(id)) {
98     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
99                       "recv data bad frame client id");
100   }
101 
102   Http2Stream *stream = cstate.find_stream(id);
103   if (stream == nullptr) {
104     if (cstate.is_valid_streamid(id)) {
105       // This error occurs fairly often, and is probably innocuous (SM initiates the shutdown)
106       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED, nullptr);
107     } else {
108       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
109                         "recv data stream freed with invalid id");
110     }
111   }
112 
113   // If a DATA frame is received whose stream is not in "open" or "half closed
114   // (local)" state,
115   // the recipient MUST respond with a stream error of type STREAM_CLOSED.
116   if (stream->get_state() != Http2StreamState::HTTP2_STREAM_STATE_OPEN &&
117       stream->get_state() != Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL) {
118     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
119                       "recv data stream closed");
120   }
121 
122   if (frame.header().flags & HTTP2_FLAGS_DATA_PADDED) {
123     frame.reader()->memcpy(&pad_length, HTTP2_DATA_PADLEN_LEN, nbytes);
124     nbytes += HTTP2_DATA_PADLEN_LEN;
125     if (pad_length > payload_length) {
126       // If the length of the padding is the length of the
127       // frame payload or greater, the recipient MUST treat this as a
128       // connection error of type PROTOCOL_ERROR.
129       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
130                         "recv data pad > payload");
131     }
132   }
133 
134   stream->increment_data_length(payload_length - pad_length - nbytes);
135   if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
136     stream->recv_end_stream = true;
137     if (!stream->change_state(frame.header().type, frame.header().flags)) {
138       cstate.send_rst_stream_frame(id, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED);
139       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
140     }
141     if (!stream->payload_length_is_valid()) {
142       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
143                         "recv data bad payload length");
144     }
145 
146     // Pure END_STREAM
147     if (payload_length == 0) {
148       stream->signal_read_event(VC_EVENT_READ_COMPLETE);
149       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
150     }
151   } else {
152     // If payload length is 0 without END_STREAM flag, do nothing
153     if (payload_length == 0) {
154       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
155     }
156   }
157 
158   // Check whether Window Size is acceptable
159   if (cstate.server_rwnd() < payload_length) {
160     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
161                       "recv data cstate.server_rwnd < payload_length");
162   }
163   if (stream->server_rwnd() < payload_length) {
164     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
165                       "recv data stream->server_rwnd < payload_length");
166   }
167 
168   // Update Window size
169   cstate.decrement_server_rwnd(payload_length);
170   stream->decrement_server_rwnd(payload_length);
171 
172   if (is_debug_tag_set("http2_con")) {
173     uint32_t rwnd = cstate.server_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
174     Http2StreamDebug(cstate.ua_session, id, "Received DATA frame: rwnd con=%zd/%" PRId32 " stream=%zd/%" PRId32,
175                      cstate.server_rwnd(), rwnd, stream->server_rwnd(), rwnd);
176   }
177 
178   const uint32_t unpadded_length = payload_length - pad_length;
179   MIOBuffer *writer              = stream->read_vio_writer();
180   if (writer == nullptr) {
181     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR);
182   }
183 
184   // If we call write() multiple times, we must keep the same reader, so we can
185   // update its offset via consume.  Otherwise, we will read the same data on the
186   // second time through
187   IOBufferReader *myreader = frame.reader()->clone();
188   // Skip pad length field
189   if (frame.header().flags & HTTP2_FLAGS_DATA_PADDED) {
190     myreader->consume(HTTP2_DATA_PADLEN_LEN);
191   }
192 
193   if (nbytes < unpadded_length) {
194     size_t read_len = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_DATA]);
195     if (nbytes + read_len > unpadded_length) {
196       read_len -= nbytes + read_len - unpadded_length;
197     }
198     unsigned int num_written = writer->write(myreader, read_len);
199     if (num_written != read_len) {
200       myreader->writer()->dealloc_reader(myreader);
201       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR);
202     }
203     myreader->consume(num_written);
204   }
205   myreader->writer()->dealloc_reader(myreader);
206 
207   if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
208     // TODO: set total written size to read_vio.nbytes
209     stream->signal_read_event(VC_EVENT_READ_COMPLETE);
210   } else {
211     stream->signal_read_event(VC_EVENT_READ_READY);
212   }
213 
214   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
215 }
216 
217 /*
218  * [RFC 7540] 6.2 HEADERS Frame
219  *
220  * NOTE: HEADERS Frame and CONTINUATION Frame
221  *   1. A HEADERS frame with the END_STREAM flag set can be followed by
222  *      CONTINUATION frames on the same stream.
223  *   2. A HEADERS frame without the END_HEADERS flag set MUST be followed by a
224  *      CONTINUATION frame
225  */
226 static Http2Error
rcv_headers_frame(Http2ConnectionState & cstate,const Http2Frame & frame)227 rcv_headers_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
228 {
229   const Http2StreamId stream_id = frame.header().streamid;
230   const uint32_t payload_length = frame.header().length;
231 
232   Http2StreamDebug(cstate.ua_session, stream_id, "Received HEADERS frame");
233 
234   if (!http2_is_client_streamid(stream_id)) {
235     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
236                       "recv headers bad client id");
237   }
238 
239   Http2Stream *stream = nullptr;
240   bool new_stream     = false;
241 
242   if (cstate.is_valid_streamid(stream_id)) {
243     stream = cstate.find_stream(stream_id);
244     if (stream == nullptr || !stream->has_trailing_header()) {
245       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
246                         "recv headers cannot find existing stream_id");
247     }
248   } else {
249     // Create new stream
250     Http2Error error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
251     stream     = cstate.create_stream(stream_id, error);
252     new_stream = true;
253     if (!stream) {
254       return error;
255     }
256   }
257 
258   // Ignoring HEADERS frame on a closed stream.  The HdrHeap has gone away and it will core.
259   if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
260     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
261   }
262 
263   Http2HeadersParameter params;
264   uint32_t header_block_fragment_offset = 0;
265   uint32_t header_block_fragment_length = payload_length;
266 
267   if (frame.header().flags & HTTP2_FLAGS_HEADERS_END_STREAM) {
268     stream->recv_end_stream = true;
269   }
270 
271   // NOTE: Strip padding if exists
272   if (frame.header().flags & HTTP2_FLAGS_HEADERS_PADDED) {
273     uint8_t buf[HTTP2_HEADERS_PADLEN_LEN] = {0};
274     frame.reader()->memcpy(buf, HTTP2_HEADERS_PADLEN_LEN);
275 
276     if (!http2_parse_headers_parameter(make_iovec(buf, HTTP2_HEADERS_PADLEN_LEN), params)) {
277       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
278                         "recv headers failed to parse");
279     }
280 
281     // Payload length can't be smaller than the pad length
282     if ((params.pad_length + HTTP2_HEADERS_PADLEN_LEN) > header_block_fragment_length) {
283       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
284                         "recv headers pad > payload length");
285     }
286 
287     header_block_fragment_offset += HTTP2_HEADERS_PADLEN_LEN;
288     header_block_fragment_length -= (HTTP2_HEADERS_PADLEN_LEN + params.pad_length);
289   }
290 
291   // NOTE: Parse priority parameters if exists
292   if (frame.header().flags & HTTP2_FLAGS_HEADERS_PRIORITY) {
293     uint8_t buf[HTTP2_PRIORITY_LEN] = {0};
294 
295     frame.reader()->memcpy(buf, HTTP2_PRIORITY_LEN, header_block_fragment_offset);
296     if (!http2_parse_priority_parameter(make_iovec(buf, HTTP2_PRIORITY_LEN), params.priority)) {
297       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
298                         "recv headers priority parameters failed parse");
299     }
300     // Protocol error if the stream depends on itself
301     if (stream_id == params.priority.stream_dependency) {
302       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
303                         "recv headers self dependency");
304     }
305 
306     // Payload length can't be smaller than the priority length
307     if (HTTP2_PRIORITY_LEN > header_block_fragment_length) {
308       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
309                         "recv priority length > payload length");
310     }
311 
312     header_block_fragment_offset += HTTP2_PRIORITY_LEN;
313     header_block_fragment_length -= HTTP2_PRIORITY_LEN;
314   }
315 
316   if (new_stream && Http2::stream_priority_enabled) {
317     Http2DependencyTree::Node *node = cstate.dependency_tree->find(stream_id);
318     if (node != nullptr) {
319       stream->priority_node = node;
320       node->t               = stream;
321     } else {
322       Http2StreamDebug(cstate.ua_session, stream_id, "HEADER PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d",
323                        params.priority.stream_dependency, params.priority.weight, params.priority.exclusive_flag,
324                        cstate.dependency_tree->size());
325 
326       stream->priority_node = cstate.dependency_tree->add(params.priority.stream_dependency, stream_id, params.priority.weight,
327                                                           params.priority.exclusive_flag, stream);
328     }
329   }
330 
331   stream->header_blocks_length = header_block_fragment_length;
332 
333   // ATS advertises SETTINGS_MAX_HEADER_LIST_SIZE as a limit of total header blocks length. (Details in [RFC 7560] 10.5.1.)
334   // Make it double to relax the limit in cases of 1) HPACK is used naively, or 2) Huffman Encoding generates large header blocks.
335   // The total "decoded" header length is strictly checked by hpack_decode_header_block().
336   if (stream->header_blocks_length > std::max(Http2::max_header_list_size, Http2::max_header_list_size * 2)) {
337     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
338                       "header blocks too large");
339   }
340 
341   stream->header_blocks = static_cast<uint8_t *>(ats_malloc(header_block_fragment_length));
342   frame.reader()->memcpy(stream->header_blocks, header_block_fragment_length, header_block_fragment_offset);
343 
344   if (frame.header().flags & HTTP2_FLAGS_HEADERS_END_HEADERS) {
345     // NOTE: If there are END_HEADERS flag, decode stored Header Blocks.
346     if (!stream->change_state(HTTP2_FRAME_TYPE_HEADERS, frame.header().flags) && stream->has_trailing_header() == false) {
347       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
348                         "recv headers end headers and not trailing header");
349     }
350 
351     bool empty_request = false;
352     if (stream->has_trailing_header()) {
353       if (!(frame.header().flags & HTTP2_FLAGS_HEADERS_END_STREAM)) {
354         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
355                           "recv headers tailing header without endstream");
356       }
357       // If the flag has already been set before decoding header blocks, this is the trailing header.
358       // Set a flag to avoid initializing fetcher for now.
359       // Decoding header blocks is stil needed to maintain a HPACK dynamic table.
360       // TODO: TS-3812
361       empty_request = true;
362     }
363 
364     stream->mark_milestone(Http2StreamMilestone::START_DECODE_HEADERS);
365     Http2ErrorCode result =
366       stream->decode_header_blocks(*cstate.local_hpack_handle, cstate.server_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
367 
368     if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
369       if (result == Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR) {
370         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR,
371                           "recv headers compression error");
372       } else if (result == Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM) {
373         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
374                           "recv headers enhance your calm");
375       } else {
376         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
377                           "recv headers malformed request");
378       }
379     }
380 
381     // Set up the State Machine
382     if (!empty_request) {
383       SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
384       stream->mark_milestone(Http2StreamMilestone::START_TXN);
385       stream->new_transaction(frame.is_from_early_data());
386       // Send request header to SM
387       stream->send_request(cstate);
388     } else {
389       // Signal VC_EVENT_READ_COMPLETE becasue received trailing header fields with END_STREAM flag
390       stream->signal_read_event(VC_EVENT_READ_COMPLETE);
391     }
392   } else {
393     // NOTE: Expect CONTINUATION Frame. Do NOT change state of stream or decode
394     // Header Blocks.
395     Http2StreamDebug(cstate.ua_session, stream_id, "No END_HEADERS flag, expecting CONTINUATION frame");
396     cstate.set_continued_stream_id(stream_id);
397   }
398 
399   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
400 }
401 
402 /*
403  * [RFC 7540] 6.3 PRIORITY
404  *
405  */
406 static Http2Error
rcv_priority_frame(Http2ConnectionState & cstate,const Http2Frame & frame)407 rcv_priority_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
408 {
409   const Http2StreamId stream_id = frame.header().streamid;
410   const uint32_t payload_length = frame.header().length;
411 
412   Http2StreamDebug(cstate.ua_session, stream_id, "Received PRIORITY frame");
413 
414   if (cstate.get_zombie_event()) {
415     Warning("Priority frame for zombied session %" PRId64, cstate.ua_session->connection_id());
416   }
417 
418   // If a PRIORITY frame is received with a stream identifier of 0x0, the
419   // recipient MUST respond with a connection error of type PROTOCOL_ERROR.
420   if (stream_id == 0) {
421     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
422                       "priority 0 stream_id");
423   }
424 
425   // A PRIORITY frame with a length other than 5 octets MUST be treated as
426   // a stream error (Section 5.4.2) of type FRAME_SIZE_ERROR.
427   if (payload_length != HTTP2_PRIORITY_LEN) {
428     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
429                       "priority bad length");
430   }
431 
432   uint8_t buf[HTTP2_PRIORITY_LEN] = {0};
433   frame.reader()->memcpy(buf, HTTP2_PRIORITY_LEN, 0);
434 
435   Http2Priority priority;
436   if (!http2_parse_priority_parameter(make_iovec(buf, HTTP2_PRIORITY_LEN), priority)) {
437     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
438                       "priority parse error");
439   }
440 
441   //  A stream cannot depend on itself.  An endpoint MUST treat this as a stream error of type PROTOCOL_ERROR.
442   if (stream_id == priority.stream_dependency) {
443     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
444                       "PRIORITY frame depends on itself");
445   }
446 
447   if (!Http2::stream_priority_enabled) {
448     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
449   }
450 
451   // Update PRIORITY frame count per minute
452   cstate.increment_received_priority_frame_count();
453   // Close this conection if its priority frame count received exceeds a limit
454   if (Http2::max_priority_frames_per_minute != 0 &&
455       cstate.get_received_priority_frame_count() > Http2::max_priority_frames_per_minute) {
456     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED, this_ethread());
457     Http2StreamDebug(cstate.ua_session, stream_id,
458                      "Observed too frequent priority changes: %u priority changes within a last minute",
459                      cstate.get_received_priority_frame_count());
460     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
461                       "recv priority too frequent priority changes");
462   }
463 
464   Http2StreamDebug(cstate.ua_session, stream_id, "PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d",
465                    priority.stream_dependency, priority.weight, priority.exclusive_flag, cstate.dependency_tree->size());
466 
467   Http2DependencyTree::Node *node = cstate.dependency_tree->find(stream_id);
468 
469   if (node != nullptr) {
470     // [RFC 7540] 5.3.3 Reprioritization
471     Http2StreamDebug(cstate.ua_session, stream_id, "Reprioritize");
472     cstate.dependency_tree->reprioritize(node, priority.stream_dependency, priority.exclusive_flag);
473     if (is_debug_tag_set("http2_priority")) {
474       std::stringstream output;
475       cstate.dependency_tree->dump_tree(output);
476       Debug("http2_priority", "[%" PRId64 "] reprioritize %s", cstate.ua_session->connection_id(), output.str().c_str());
477     }
478   } else {
479     // PRIORITY frame is received before HEADERS frame.
480 
481     // Restrict number of inactive node in dependency tree smaller than max_concurrent_streams.
482     // Current number of inactive node is size of tree minus active node count.
483     if (Http2::max_concurrent_streams_in > cstate.dependency_tree->size() - cstate.get_client_stream_count() + 1) {
484       cstate.dependency_tree->add(priority.stream_dependency, stream_id, priority.weight, priority.exclusive_flag, nullptr);
485     }
486   }
487 
488   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
489 }
490 
491 static Http2Error
rcv_rst_stream_frame(Http2ConnectionState & cstate,const Http2Frame & frame)492 rcv_rst_stream_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
493 {
494   Http2RstStream rst_stream;
495   char buf[HTTP2_RST_STREAM_LEN];
496   char *end;
497   const Http2StreamId stream_id = frame.header().streamid;
498 
499   Http2StreamDebug(cstate.ua_session, frame.header().streamid, "Received RST_STREAM frame");
500 
501   // RST_STREAM frames MUST be associated with a stream.  If a RST_STREAM
502   // frame is received with a stream identifier of 0x0, the recipient MUST
503   // treat this as a connection error (Section 5.4.1) of type
504   // PROTOCOL_ERROR.
505   if (stream_id == 0) {
506     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
507                       "reset access stream with invalid id");
508   }
509 
510   Http2Stream *stream = cstate.find_stream(stream_id);
511   if (stream == nullptr) {
512     if (cstate.is_valid_streamid(stream_id)) {
513       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
514     } else {
515       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
516                         "reset frame bad id stream not found");
517     }
518   }
519 
520   // A RST_STREAM frame with a length other than 4 octets MUST be treated
521   // as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.
522   if (frame.header().length != HTTP2_RST_STREAM_LEN) {
523     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
524                       "reset frame wrong length");
525   }
526 
527   if (stream == nullptr || !stream->change_state(frame.header().type, frame.header().flags)) {
528     // If a RST_STREAM frame identifying an idle stream is received, the
529     // recipient MUST treat this as a connection error of type PROTOCOL_ERROR.
530     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
531                       "reset missing stream or bad stream state");
532   }
533 
534   end = frame.reader()->memcpy(buf, sizeof(buf), 0);
535 
536   if (!http2_parse_rst_stream(make_iovec(buf, end - buf), rst_stream)) {
537     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
538                       "reset failed to parse");
539   }
540 
541   if (stream != nullptr) {
542     Http2StreamDebug(cstate.ua_session, stream_id, "RST_STREAM: Error Code: %u", rst_stream.error_code);
543 
544     stream->set_rx_error_code({ProxyErrorClass::TXN, static_cast<uint32_t>(rst_stream.error_code)});
545     stream->initiating_close();
546   }
547 
548   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
549 }
550 
551 static Http2Error
rcv_settings_frame(Http2ConnectionState & cstate,const Http2Frame & frame)552 rcv_settings_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
553 {
554   Http2SettingsParameter param;
555   char buf[HTTP2_SETTINGS_PARAMETER_LEN];
556   unsigned nbytes               = 0;
557   const Http2StreamId stream_id = frame.header().streamid;
558 
559   Http2StreamDebug(cstate.ua_session, stream_id, "Received SETTINGS frame");
560 
561   if (cstate.get_zombie_event()) {
562     Warning("Setting frame for zombied session %" PRId64, cstate.ua_session->connection_id());
563   }
564 
565   // Update SETTIGNS frame count per minute
566   cstate.increment_received_settings_frame_count();
567   // Close this conection if its SETTINGS frame count exceeds a limit
568   if (cstate.get_received_settings_frame_count() > Http2::max_settings_frames_per_minute) {
569     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED, this_ethread());
570     Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent SETTINGS frames: %u frames within a last minute",
571                      cstate.get_received_settings_frame_count());
572     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
573                       "recv settings too frequent SETTINGS frames");
574   }
575 
576   // [RFC 7540] 6.5. The stream identifier for a SETTINGS frame MUST be zero.
577   // If an endpoint receives a SETTINGS frame whose stream identifier field is
578   // anything other than 0x0, the endpoint MUST respond with a connection
579   // error (Section 5.4.1) of type PROTOCOL_ERROR.
580   if (stream_id != 0) {
581     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
582                       "recv settings stream not 0");
583   }
584 
585   // [RFC 7540] 6.5. Receipt of a SETTINGS frame with the ACK flag set and a
586   // length field value other than 0 MUST be treated as a connection
587   // error of type FRAME_SIZE_ERROR.
588   if (frame.header().flags & HTTP2_FLAGS_SETTINGS_ACK) {
589     if (frame.header().length == 0) {
590       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
591     } else {
592       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
593                         "recv settings ACK header length not 0");
594     }
595   }
596 
597   // A SETTINGS frame with a length other than a multiple of 6 octets MUST
598   // be treated as a connection error (Section 5.4.1) of type
599   // FRAME_SIZE_ERROR.
600   if (frame.header().length % 6 != 0) {
601     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
602                       "recv settings header wrong length");
603   }
604 
605   uint32_t n_settings = 0;
606   while (nbytes < frame.header().length) {
607     if (n_settings >= Http2::max_settings_per_frame) {
608       HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED, this_ethread());
609       Http2StreamDebug(cstate.ua_session, stream_id, "Observed too many settings in a frame");
610       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
611                         "recv settings too many settings in a frame");
612     }
613 
614     unsigned read_bytes = read_rcv_buffer(buf, sizeof(buf), nbytes, frame);
615 
616     if (!http2_parse_settings_parameter(make_iovec(buf, read_bytes), param)) {
617       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
618                         "recv settings parse failed");
619     }
620 
621     if (!http2_settings_parameter_is_valid(param)) {
622       if (param.id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
623         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
624                           "recv settings bad initial window size");
625       } else {
626         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
627                           "recv settings bad param");
628       }
629     }
630 
631     Http2StreamDebug(cstate.ua_session, stream_id, "   %s : %u", Http2DebugNames::get_settings_param_name(param.id), param.value);
632 
633     // [RFC 7540] 6.9.2. When the value of SETTINGS_INITIAL_WINDOW_SIZE
634     // changes, a receiver MUST adjust the size of all stream flow control
635     // windows that it maintains by the difference between the new value and
636     // the old value.
637     if (param.id == HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) {
638       cstate.update_initial_rwnd(param.value);
639     }
640 
641     cstate.client_settings.set(static_cast<Http2SettingsIdentifier>(param.id), param.value);
642     ++n_settings;
643   }
644 
645   // Update settigs count per minute
646   cstate.increment_received_settings_count(n_settings);
647   // Close this conection if its settings count received exceeds a limit
648   if (cstate.get_received_settings_count() > Http2::max_settings_per_minute) {
649     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED, this_ethread());
650     Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent setting changes: %u settings within a last minute",
651                      cstate.get_received_settings_count());
652     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
653                       "recv settings too frequent setting changes");
654   }
655 
656   // [RFC 7540] 6.5. Once all values have been applied, the recipient MUST
657   // immediately emit a SETTINGS frame with the ACK flag set.
658   Http2SettingsFrame ack_frame(0, HTTP2_FLAGS_SETTINGS_ACK);
659   cstate.ua_session->xmit(ack_frame);
660 
661   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
662 }
663 
664 static Http2Error
rcv_push_promise_frame(Http2ConnectionState & cstate,const Http2Frame & frame)665 rcv_push_promise_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
666 {
667   Http2StreamDebug(cstate.ua_session, frame.header().streamid, "Received PUSH_PROMISE frame");
668 
669   // [RFC 7540] 8.2. A client cannot push. Thus, servers MUST treat the receipt of a
670   // PUSH_PROMISE frame as a connection error of type PROTOCOL_ERROR.
671   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
672                     "promise not allowed");
673 }
674 
675 static Http2Error
rcv_ping_frame(Http2ConnectionState & cstate,const Http2Frame & frame)676 rcv_ping_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
677 {
678   uint8_t opaque_data[HTTP2_PING_LEN];
679   const Http2StreamId stream_id = frame.header().streamid;
680 
681   Http2StreamDebug(cstate.ua_session, stream_id, "Received PING frame");
682 
683   cstate.schedule_zombie_event();
684 
685   //  If a PING frame is received with a stream identifier field value other
686   //  than 0x0, the recipient MUST respond with a connection error of type
687   //  PROTOCOL_ERROR.
688   if (stream_id != 0x0) {
689     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR, "ping id not 0");
690   }
691 
692   // Receipt of a PING frame with a length field value other than 8 MUST
693   // be treated as a connection error (Section 5.4.1) of type FRAME_SIZE_ERROR.
694   if (frame.header().length != HTTP2_PING_LEN) {
695     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
696                       "ping bad length");
697   }
698 
699   // Update PING frame count per minute
700   cstate.increment_received_ping_frame_count();
701   // Close this conection if its ping count received exceeds a limit
702   if (cstate.get_received_ping_frame_count() > Http2::max_ping_frames_per_minute) {
703     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED, this_ethread());
704     Http2StreamDebug(cstate.ua_session, stream_id, "Observed too frequent PING frames: %u PING frames within a last minute",
705                      cstate.get_received_ping_frame_count());
706     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
707                       "recv ping too frequent PING frame");
708   }
709 
710   // An endpoint MUST NOT respond to PING frames containing this flag.
711   if (frame.header().flags & HTTP2_FLAGS_PING_ACK) {
712     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
713   }
714 
715   frame.reader()->memcpy(opaque_data, HTTP2_PING_LEN, 0);
716 
717   // ACK (0x1): An endpoint MUST set this flag in PING responses.
718   cstate.send_ping_frame(stream_id, HTTP2_FLAGS_PING_ACK, opaque_data);
719 
720   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
721 }
722 
723 static Http2Error
rcv_goaway_frame(Http2ConnectionState & cstate,const Http2Frame & frame)724 rcv_goaway_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
725 {
726   Http2Goaway goaway;
727   char buf[HTTP2_GOAWAY_LEN];
728   unsigned nbytes               = 0;
729   const Http2StreamId stream_id = frame.header().streamid;
730 
731   Http2StreamDebug(cstate.ua_session, stream_id, "Received GOAWAY frame");
732 
733   // An endpoint MUST treat a GOAWAY frame with a stream identifier other
734   // than 0x0 as a connection error of type PROTOCOL_ERROR.
735   if (stream_id != 0x0) {
736     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
737                       "goaway id non-zero");
738   }
739 
740   while (nbytes < frame.header().length) {
741     unsigned read_bytes = read_rcv_buffer(buf, sizeof(buf), nbytes, frame);
742 
743     if (!http2_parse_goaway(make_iovec(buf, read_bytes), goaway)) {
744       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
745                         "goaway failed parse");
746     }
747   }
748 
749   Http2StreamDebug(cstate.ua_session, stream_id, "GOAWAY: last stream id=%d, error code=%d", goaway.last_streamid,
750                    static_cast<int>(goaway.error_code));
751 
752   cstate.rx_error_code = {ProxyErrorClass::SSN, static_cast<uint32_t>(goaway.error_code)};
753   cstate.handleEvent(HTTP2_SESSION_EVENT_FINI, nullptr);
754 
755   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
756 }
757 
758 static Http2Error
rcv_window_update_frame(Http2ConnectionState & cstate,const Http2Frame & frame)759 rcv_window_update_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
760 {
761   char buf[HTTP2_WINDOW_UPDATE_LEN];
762   uint32_t size;
763   const Http2StreamId stream_id = frame.header().streamid;
764 
765   //  A WINDOW_UPDATE frame with a length other than 4 octets MUST be
766   //  treated as a connection error of type FRAME_SIZE_ERROR.
767   if (frame.header().length != HTTP2_WINDOW_UPDATE_LEN) {
768     Http2StreamDebug(cstate.ua_session, stream_id, "Received WINDOW_UPDATE frame - length incorrect");
769     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FRAME_SIZE_ERROR,
770                       "window update bad length");
771   }
772 
773   frame.reader()->memcpy(buf, sizeof(buf), 0);
774   http2_parse_window_update(make_iovec(buf, sizeof(buf)), size);
775 
776   // A receiver MUST treat the receipt of a WINDOW_UPDATE frame with a flow
777   // control window increment of 0 as a connection error of type PROTOCOL_ERROR;
778   if (size == 0) {
779     if (stream_id == 0) {
780       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
781                         "window update length=0 and id=0");
782     } else {
783       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
784                         "window update length=0");
785     }
786   }
787 
788   if (stream_id == 0) {
789     // Connection level window update
790     Http2StreamDebug(cstate.ua_session, stream_id, "Received WINDOW_UPDATE frame - updated to: %zd delta: %u",
791                      (cstate.client_rwnd() + size), size);
792 
793     // A sender MUST NOT allow a flow-control window to exceed 2^31-1
794     // octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
795     // control window to exceed this maximum, it MUST terminate either the
796     // stream or the connection, as appropriate.  For streams, the sender
797     // sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
798     // connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
799     // is sent.
800     if (size > HTTP2_MAX_WINDOW_SIZE - cstate.client_rwnd()) {
801       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
802                         "window update too big");
803     }
804 
805     auto error = cstate.increment_client_rwnd(size);
806     if (error != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
807       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, error);
808     }
809 
810     cstate.restart_streams();
811   } else {
812     // Stream level window update
813     Http2Stream *stream = cstate.find_stream(stream_id);
814 
815     if (stream == nullptr) {
816       if (cstate.is_valid_streamid(stream_id)) {
817         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
818       } else {
819         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
820                           "window update stream invalid id");
821       }
822     }
823 
824     Http2StreamDebug(cstate.ua_session, stream_id, "Received WINDOW_UPDATE frame - updated to: %zd delta: %u",
825                      (stream->client_rwnd() + size), size);
826 
827     // A sender MUST NOT allow a flow-control window to exceed 2^31-1
828     // octets.  If a sender receives a WINDOW_UPDATE that causes a flow-
829     // control window to exceed this maximum, it MUST terminate either the
830     // stream or the connection, as appropriate.  For streams, the sender
831     // sends a RST_STREAM with an error code of FLOW_CONTROL_ERROR; for the
832     // connection, a GOAWAY frame with an error code of FLOW_CONTROL_ERROR
833     // is sent.
834     if (size > HTTP2_MAX_WINDOW_SIZE - stream->client_rwnd()) {
835       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
836                         "window update too big 2");
837     }
838 
839     auto error = stream->increment_client_rwnd(size);
840     if (error != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
841       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, error);
842     }
843 
844     ssize_t wnd = std::min(cstate.client_rwnd(), stream->client_rwnd());
845     if (!stream->is_closed() && stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE && wnd > 0) {
846       SCOPED_MUTEX_LOCK(lock, stream->mutex, this_ethread());
847       stream->restart_sending();
848     }
849   }
850 
851   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
852 }
853 
854 /*
855  * [RFC 7540] 6.10 CONTINUATION
856  *
857  * NOTE: Logically, the CONTINUATION frames are part of the HEADERS frame. ([RFC
858  *7540] 6.2 HEADERS)
859  *
860  */
861 static Http2Error
rcv_continuation_frame(Http2ConnectionState & cstate,const Http2Frame & frame)862 rcv_continuation_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
863 {
864   const Http2StreamId stream_id = frame.header().streamid;
865   const uint32_t payload_length = frame.header().length;
866 
867   Http2StreamDebug(cstate.ua_session, stream_id, "Received CONTINUATION frame");
868 
869   if (!http2_is_client_streamid(stream_id)) {
870     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
871                       "continuation bad client id");
872   }
873 
874   // Find opened stream
875   // CONTINUATION frames MUST be associated with a stream.  If a
876   // CONTINUATION frame is received whose stream identifier field is 0x0,
877   // the recipient MUST respond with a connection error ([RFC 7540] Section
878   // 5.4.1) of type PROTOCOL_ERROR.
879   Http2Stream *stream = cstate.find_stream(stream_id);
880   if (stream == nullptr) {
881     if (cstate.is_valid_streamid(stream_id)) {
882       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
883                         "continuation stream freed with valid id");
884     } else {
885       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
886                         "continuation stream freed with invalid id");
887     }
888   } else {
889     switch (stream->get_state()) {
890     case Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE:
891       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_STREAM_CLOSED,
892                         "continuation half close remote");
893     case Http2StreamState::HTTP2_STREAM_STATE_IDLE:
894       break;
895     default:
896       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
897                         "continuation bad state");
898     }
899   }
900 
901   uint32_t header_blocks_offset = stream->header_blocks_length;
902   stream->header_blocks_length += payload_length;
903 
904   // ATS advertises SETTINGS_MAX_HEADER_LIST_SIZE as a limit of total header blocks length. (Details in [RFC 7560] 10.5.1.)
905   // Make it double to relax the limit in cases of 1) HPACK is used naively, or 2) Huffman Encoding generates large header blocks.
906   // The total "decoded" header length is strictly checked by hpack_decode_header_block().
907   if (stream->header_blocks_length > std::max(Http2::max_header_list_size, Http2::max_header_list_size * 2)) {
908     return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
909                       "header blocks too large");
910   }
911 
912   stream->header_blocks = static_cast<uint8_t *>(ats_realloc(stream->header_blocks, stream->header_blocks_length));
913   frame.reader()->memcpy(stream->header_blocks + header_blocks_offset, payload_length);
914 
915   if (frame.header().flags & HTTP2_FLAGS_HEADERS_END_HEADERS) {
916     // NOTE: If there are END_HEADERS flag, decode stored Header Blocks.
917     cstate.clear_continued_stream_id();
918 
919     if (!stream->change_state(HTTP2_FRAME_TYPE_CONTINUATION, frame.header().flags)) {
920       return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
921                         "continuation no state change");
922     }
923 
924     Http2ErrorCode result =
925       stream->decode_header_blocks(*cstate.local_hpack_handle, cstate.server_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
926 
927     if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
928       if (result == Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR) {
929         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR,
930                           "continuation compression error");
931       } else if (result == Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM) {
932         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM,
933                           "continuation enhance your calm");
934       } else {
935         return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
936                           "continuation malformed request");
937       }
938     }
939 
940     // Set up the State Machine
941     SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
942     stream->mark_milestone(Http2StreamMilestone::START_TXN);
943     // This should be fine, need to verify whether we need to replace this with the
944     // "from_early_data" flag from the associated HEADERS frame.
945     stream->new_transaction(frame.is_from_early_data());
946     // Send request header to SM
947     stream->send_request(cstate);
948   } else {
949     // NOTE: Expect another CONTINUATION Frame. Do nothing.
950     Http2StreamDebug(cstate.ua_session, stream_id, "No END_HEADERS flag, expecting CONTINUATION frame");
951   }
952 
953   return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
954 }
955 
956 static const http2_frame_dispatch frame_handlers[HTTP2_FRAME_TYPE_MAX] = {
957   rcv_data_frame,          // HTTP2_FRAME_TYPE_DATA
958   rcv_headers_frame,       // HTTP2_FRAME_TYPE_HEADERS
959   rcv_priority_frame,      // HTTP2_FRAME_TYPE_PRIORITY
960   rcv_rst_stream_frame,    // HTTP2_FRAME_TYPE_RST_STREAM
961   rcv_settings_frame,      // HTTP2_FRAME_TYPE_SETTINGS
962   rcv_push_promise_frame,  // HTTP2_FRAME_TYPE_PUSH_PROMISE
963   rcv_ping_frame,          // HTTP2_FRAME_TYPE_PING
964   rcv_goaway_frame,        // HTTP2_FRAME_TYPE_GOAWAY
965   rcv_window_update_frame, // HTTP2_FRAME_TYPE_WINDOW_UPDATE
966   rcv_continuation_frame,  // HTTP2_FRAME_TYPE_CONTINUATION
967 };
968 
969 int
main_event_handler(int event,void * edata)970 Http2ConnectionState::main_event_handler(int event, void *edata)
971 {
972   if (edata == zombie_event) {
973     // zombie session is still around. Assert
974     ink_release_assert(zombie_event == nullptr);
975   } else if (edata == fini_event) {
976     fini_event = nullptr;
977   }
978   ++recursion;
979   switch (event) {
980   // Initialize HTTP/2 Connection
981   case HTTP2_SESSION_EVENT_INIT: {
982     ink_assert(this->ua_session == nullptr);
983     this->ua_session = static_cast<Http2ClientSession *>(edata);
984     REMEMBER(event, this->recursion);
985 
986     // [RFC 7540] 3.5. HTTP/2 Connection Preface. Upon establishment of a TCP connection and
987     // determination that HTTP/2 will be used by both peers, each endpoint MUST
988     // send a connection preface as a final confirmation ... The server
989     // connection
990     // preface consists of a potentially empty SETTINGS frame.
991 
992     // Load the server settings from the records.config / RecordsConfig.cc
993     // settings.
994     Http2ConnectionSettings configured_settings;
995     configured_settings.settings_from_configs();
996     configured_settings.set(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, _adjust_concurrent_stream());
997 
998     send_settings_frame(configured_settings);
999 
1000     if (server_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) > HTTP2_INITIAL_WINDOW_SIZE) {
1001       send_window_update_frame(0, server_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) - HTTP2_INITIAL_WINDOW_SIZE);
1002     }
1003 
1004     break;
1005   }
1006 
1007   // Finalize HTTP/2 Connection
1008   case HTTP2_SESSION_EVENT_FINI: {
1009     SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
1010     REMEMBER(event, this->recursion);
1011 
1012     ink_assert(this->fini_received == false);
1013     this->fini_received = true;
1014     cleanup_streams();
1015     release_stream();
1016     SET_HANDLER(&Http2ConnectionState::state_closed);
1017   } break;
1018 
1019   case HTTP2_SESSION_EVENT_XMIT: {
1020     REMEMBER(event, this->recursion);
1021     SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
1022     send_data_frames_depends_on_priority();
1023     _scheduled = false;
1024   } break;
1025 
1026   // Parse received HTTP/2 frames
1027   case HTTP2_SESSION_EVENT_RECV: {
1028     REMEMBER(event, this->recursion);
1029     const Http2Frame *frame       = static_cast<Http2Frame *>(edata);
1030     const Http2StreamId stream_id = frame->header().streamid;
1031     Http2Error error;
1032 
1033     // [RFC 7540] 5.5. Extending HTTP/2
1034     //   Implementations MUST discard frames that have unknown or unsupported types.
1035     if (frame->header().type >= HTTP2_FRAME_TYPE_MAX) {
1036       Http2StreamDebug(ua_session, stream_id, "Discard a frame which has unknown type, type=%x", frame->header().type);
1037       break;
1038     }
1039 
1040     // We need to be careful here, certain frame types are not safe over 0-rtt, tentative for now.
1041     // DATA:          NO
1042     // HEADERS:       YES (safe http methods only, can only be checked after parsing the payload).
1043     // PRIORITY:      YES
1044     // RST_STREAM:    NO
1045     // SETTINGS:      YES
1046     // PUSH_PROMISE:  NO
1047     // PING:          YES
1048     // GOAWAY:        NO
1049     // WINDOW_UPDATE: YES
1050     // CONTINUATION:  YES (safe http methods only, same as HEADERS frame).
1051     if (frame->is_from_early_data() &&
1052         (frame->header().type == HTTP2_FRAME_TYPE_DATA || frame->header().type == HTTP2_FRAME_TYPE_RST_STREAM ||
1053          frame->header().type == HTTP2_FRAME_TYPE_PUSH_PROMISE || frame->header().type == HTTP2_FRAME_TYPE_GOAWAY)) {
1054       Http2StreamDebug(ua_session, stream_id, "Discard a frame which is received from early data and has type=%x",
1055                        frame->header().type);
1056       break;
1057     }
1058 
1059     if (frame_handlers[frame->header().type]) {
1060       error = frame_handlers[frame->header().type](*this, *frame);
1061     } else {
1062       error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_INTERNAL_ERROR, "no handler");
1063     }
1064 
1065     if (error.cls != Http2ErrorClass::HTTP2_ERROR_CLASS_NONE) {
1066       ip_port_text_buffer ipb;
1067       const char *client_ip = ats_ip_ntop(ua_session->get_client_addr(), ipb, sizeof(ipb));
1068       if (error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION) {
1069         if (error.msg) {
1070           Error("HTTP/2 connection error code=0x%02x client_ip=%s session_id=%" PRId64 " stream_id=%u %s",
1071                 static_cast<int>(error.code), client_ip, ua_session->connection_id(), stream_id, error.msg);
1072         }
1073         this->send_goaway_frame(this->latest_streamid_in, error.code);
1074         this->ua_session->set_half_close_local_flag(true);
1075         if (fini_event == nullptr) {
1076           fini_event = this_ethread()->schedule_imm_local((Continuation *)this, HTTP2_SESSION_EVENT_FINI);
1077         }
1078 
1079         // The streams will be cleaned up by the HTTP2_SESSION_EVENT_FINI event
1080         // The Http2ClientSession will shutdown because connection_state.is_state_closed() will be true
1081       } else if (error.cls == Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM) {
1082         if (error.msg) {
1083           Error("HTTP/2 stream error code=0x%02x client_ip=%s session_id=%" PRId64 " stream_id=%u %s", static_cast<int>(error.code),
1084                 client_ip, ua_session->connection_id(), stream_id, error.msg);
1085         }
1086         this->send_rst_stream_frame(stream_id, error.code);
1087       }
1088     }
1089 
1090   } break;
1091 
1092   // Initiate a gracefull shutdown
1093   case HTTP2_SESSION_EVENT_SHUTDOWN_INIT: {
1094     REMEMBER(event, this->recursion);
1095     ink_assert(shutdown_state == HTTP2_SHUTDOWN_NOT_INITIATED);
1096     shutdown_state = HTTP2_SHUTDOWN_INITIATED;
1097     // [RFC 7540] 6.8.  GOAWAY
1098     // A server that is attempting to gracefully shut down a
1099     // connection SHOULD send an initial GOAWAY frame with the last stream
1100     // identifier set to 2^31-1 and a NO_ERROR code.
1101     send_goaway_frame(INT32_MAX, Http2ErrorCode::HTTP2_ERROR_NO_ERROR);
1102     // After allowing time for any in-flight stream creation (at least one round-trip time),
1103     shutdown_cont_event = this_ethread()->schedule_in((Continuation *)this, HRTIME_SECONDS(2), HTTP2_SESSION_EVENT_SHUTDOWN_CONT);
1104   } break;
1105 
1106   // Continue a gracefull shutdown
1107   case HTTP2_SESSION_EVENT_SHUTDOWN_CONT: {
1108     REMEMBER(event, this->recursion);
1109     ink_assert(shutdown_state == HTTP2_SHUTDOWN_INITIATED);
1110     shutdown_cont_event = nullptr;
1111     shutdown_state      = HTTP2_SHUTDOWN_IN_PROGRESS;
1112     // [RFC 7540] 6.8.  GOAWAY
1113     // ..., the server can send another GOAWAY frame with an updated last stream identifier
1114     if (shutdown_reason == Http2ErrorCode::HTTP2_ERROR_MAX) {
1115       shutdown_reason = Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
1116     }
1117     send_goaway_frame(latest_streamid_in, shutdown_reason);
1118     // Stop creating new streams
1119     SCOPED_MUTEX_LOCK(lock, this->ua_session->mutex, this_ethread());
1120     this->ua_session->set_half_close_local_flag(true);
1121   } break;
1122 
1123   default:
1124     Http2ConDebug(ua_session, "unexpected event=%d edata=%p", event, edata);
1125     ink_release_assert(0);
1126     break;
1127   }
1128 
1129   --recursion;
1130   if (recursion == 0 && ua_session && !ua_session->is_recursing()) {
1131     if (this->ua_session->ready_to_free()) {
1132       MUTEX_TRY_LOCK(lock, this->ua_session->mutex, this_ethread());
1133       if (lock.is_locked()) {
1134         this->ua_session->free();
1135         // After the free, the Http2ConnectionState object is also freed.
1136         // The Http2ConnectionState object is allocted within the Http2ClientSession object
1137       }
1138     }
1139   }
1140 
1141   return 0;
1142 }
1143 
1144 int
state_closed(int event,void * edata)1145 Http2ConnectionState::state_closed(int event, void *edata)
1146 {
1147   REMEMBER(event, this->recursion);
1148 
1149   if (edata == zombie_event) {
1150     // Zombie session is still around.  Assert!
1151     ink_release_assert(zombie_event == nullptr);
1152   } else if (edata == fini_event) {
1153     fini_event = nullptr;
1154   } else if (edata == shutdown_cont_event) {
1155     shutdown_cont_event = nullptr;
1156   }
1157   return 0;
1158 }
1159 
1160 Http2Stream *
create_stream(Http2StreamId new_id,Http2Error & error)1161 Http2ConnectionState::create_stream(Http2StreamId new_id, Http2Error &error)
1162 {
1163   // first check if we've hit the active connection limit
1164   if (!ua_session->get_netvc()->add_to_active_queue()) {
1165     error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_NO_ERROR,
1166                        "refused to create new stream, maxed out active connections");
1167     return nullptr;
1168   }
1169 
1170   // In half_close state, TS doesn't create new stream. Because GOAWAY frame is sent to client
1171   if (ua_session->get_half_close_local_flag()) {
1172     error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
1173                        "refused to create new stream, because ua_session is in half_close state");
1174     return nullptr;
1175   }
1176 
1177   bool client_streamid = http2_is_client_streamid(new_id);
1178 
1179   // 5.1.1 The identifier of a newly established stream MUST be numerically
1180   // greater than all streams that the initiating endpoint has opened or
1181   // reserved.  This governs streams that are opened using a HEADERS frame
1182   // and streams that are reserved using PUSH_PROMISE.  An endpoint that
1183   // receives an unexpected stream identifier MUST respond with a
1184   // connection error (Section 5.4.1) of type PROTOCOL_ERROR.
1185   if (client_streamid) {
1186     if (new_id <= latest_streamid_in) {
1187       error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
1188                          "recv headers new client id less than latest stream id");
1189       return nullptr;
1190     }
1191   } else {
1192     if (new_id <= latest_streamid_out) {
1193       error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR,
1194                          "recv headers new server id less than latest stream id");
1195       return nullptr;
1196     }
1197   }
1198 
1199   // Endpoints MUST NOT exceed the limit set by their peer.  An endpoint
1200   // that receives a HEADERS frame that causes their advertised concurrent
1201   // stream limit to be exceeded MUST treat this as a stream error.
1202   if (client_streamid) {
1203     if (client_streams_in_count >= server_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) {
1204       error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
1205                          "recv headers creating inbound stream beyond max_concurrent limit");
1206       return nullptr;
1207     }
1208   } else {
1209     if (client_streams_out_count >= client_settings.get(HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS)) {
1210       error = Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_STREAM, Http2ErrorCode::HTTP2_ERROR_REFUSED_STREAM,
1211                          "recv headers creating outbound stream beyond max_concurrent limit");
1212       return nullptr;
1213     }
1214   }
1215 
1216   Http2Stream *new_stream = THREAD_ALLOC_INIT(http2StreamAllocator, this_ethread());
1217   new_stream->init(new_id, client_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE));
1218 
1219   ink_assert(nullptr != new_stream);
1220   ink_assert(!stream_list.in(new_stream));
1221 
1222   stream_list.enqueue(new_stream);
1223   if (client_streamid) {
1224     latest_streamid_in = new_id;
1225     ink_assert(client_streams_in_count < UINT32_MAX);
1226     ++client_streams_in_count;
1227   } else {
1228     latest_streamid_out = new_id;
1229     ink_assert(client_streams_out_count < UINT32_MAX);
1230     ++client_streams_out_count;
1231   }
1232   ++total_client_streams_count;
1233 
1234   if (zombie_event != nullptr) {
1235     zombie_event->cancel();
1236     zombie_event = nullptr;
1237   }
1238 
1239   new_stream->set_proxy_ssn(ua_session);
1240   new_stream->mutex                     = new_ProxyMutex();
1241   new_stream->is_first_transaction_flag = get_stream_requests() == 0;
1242   increment_stream_requests();
1243 
1244   return new_stream;
1245 }
1246 
1247 Http2Stream *
find_stream(Http2StreamId id) const1248 Http2ConnectionState::find_stream(Http2StreamId id) const
1249 {
1250   for (Http2Stream *s = stream_list.head; s; s = static_cast<Http2Stream *>(s->link.next)) {
1251     if (s->get_id() == id) {
1252       return s;
1253     }
1254     ink_assert(s != s->link.next);
1255   }
1256   return nullptr;
1257 }
1258 
1259 void
restart_streams()1260 Http2ConnectionState::restart_streams()
1261 {
1262   Http2Stream *s = stream_list.head;
1263   if (s) {
1264     Http2Stream *end = s;
1265 
1266     // This is a static variable, so it is shared in Http2ConnectionState instances and will get incremented in subsequent calls.
1267     // It doesn't need to be initialized with rand() nor time(), and doesn't need to be accessed with a lock, because it doesn't
1268     // need that randomness and accuracy.
1269     static uint16_t starting_point = 0;
1270 
1271     // Change the start point randomly
1272     for (int i = starting_point % total_client_streams_count; i >= 0; --i) {
1273       end = static_cast<Http2Stream *>(end->link.next ? end->link.next : stream_list.head);
1274     }
1275     s = static_cast<Http2Stream *>(end->link.next ? end->link.next : stream_list.head);
1276 
1277     // Call send_response_body() for each streams
1278     while (s != end) {
1279       Http2Stream *next = static_cast<Http2Stream *>(s->link.next ? s->link.next : stream_list.head);
1280       if (!s->is_closed() && s->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE &&
1281           std::min(this->client_rwnd(), s->client_rwnd()) > 0) {
1282         SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
1283         s->restart_sending();
1284       }
1285       ink_assert(s != next);
1286       s = next;
1287     }
1288     if (!s->is_closed() && s->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE &&
1289         std::min(this->client_rwnd(), s->client_rwnd()) > 0) {
1290       SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
1291       s->restart_sending();
1292     }
1293 
1294     ++starting_point;
1295   }
1296 }
1297 
1298 void
restart_receiving(Http2Stream * stream)1299 Http2ConnectionState::restart_receiving(Http2Stream *stream)
1300 {
1301   uint32_t initial_rwnd = this->server_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE);
1302   uint32_t min_rwnd     = std::min(initial_rwnd, this->server_settings.get(HTTP2_SETTINGS_MAX_FRAME_SIZE));
1303 
1304   // Connection level WINDOW UPDATE
1305   if (this->server_rwnd() < min_rwnd) {
1306     Http2WindowSize diff_size = initial_rwnd - this->server_rwnd();
1307     this->increment_server_rwnd(diff_size);
1308     this->send_window_update_frame(0, diff_size);
1309   }
1310 
1311   // Stream level WINDOW UPDATE
1312   if (stream == nullptr || stream->server_rwnd() >= min_rwnd) {
1313     return;
1314   }
1315 
1316   // If read_vio is buffering data, do not fully update window
1317   int64_t data_size = stream->read_vio_read_avail();
1318   if (data_size >= initial_rwnd) {
1319     return;
1320   }
1321 
1322   Http2WindowSize diff_size = initial_rwnd - std::max(static_cast<int64_t>(stream->server_rwnd()), data_size);
1323   stream->increment_server_rwnd(diff_size);
1324   this->send_window_update_frame(stream->get_id(), diff_size);
1325 }
1326 
1327 void
cleanup_streams()1328 Http2ConnectionState::cleanup_streams()
1329 {
1330   Http2Stream *s = stream_list.head;
1331   while (s) {
1332     Http2Stream *next = static_cast<Http2Stream *>(s->link.next);
1333     if (this->rx_error_code.cls != ProxyErrorClass::NONE) {
1334       s->set_rx_error_code(this->rx_error_code);
1335     }
1336     if (this->tx_error_code.cls != ProxyErrorClass::NONE) {
1337       s->set_tx_error_code(this->tx_error_code);
1338     }
1339     s->initiating_close();
1340     ink_assert(s != next);
1341     s = next;
1342   }
1343 
1344   if (!is_state_closed()) {
1345     SCOPED_MUTEX_LOCK(lock, this->ua_session->mutex, this_ethread());
1346 
1347     UnixNetVConnection *vc = static_cast<UnixNetVConnection *>(ua_session->get_netvc());
1348     if (vc && vc->active_timeout_in == 0) {
1349       vc->add_to_keep_alive_queue();
1350     }
1351   }
1352 }
1353 
1354 bool
delete_stream(Http2Stream * stream)1355 Http2ConnectionState::delete_stream(Http2Stream *stream)
1356 {
1357   ink_assert(nullptr != stream);
1358   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
1359 
1360   // If stream has already been removed from the list, just go on
1361   if (!stream_list.in(stream)) {
1362     return false;
1363   }
1364 
1365   Http2StreamDebug(ua_session, stream->get_id(), "Delete stream");
1366   REMEMBER(NO_EVENT, this->recursion);
1367 
1368   if (Http2::stream_priority_enabled) {
1369     Http2DependencyTree::Node *node = stream->priority_node;
1370     if (node != nullptr) {
1371       if (node->active) {
1372         dependency_tree->deactivate(node, 0);
1373       }
1374       if (is_debug_tag_set("http2_priority")) {
1375         std::stringstream output;
1376         dependency_tree->dump_tree(output);
1377         Debug("http2_priority", "[%" PRId64 "] %s", ua_session->connection_id(), output.str().c_str());
1378       }
1379       dependency_tree->remove(node);
1380       // ink_release_assert(dependency_tree->find(stream->get_id()) == nullptr);
1381     }
1382     stream->priority_node = nullptr;
1383   }
1384 
1385   if (stream->get_state() != Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
1386     send_rst_stream_frame(stream->get_id(), Http2ErrorCode::HTTP2_ERROR_NO_ERROR);
1387   }
1388 
1389   stream_list.remove(stream);
1390   if (http2_is_client_streamid(stream->get_id())) {
1391     ink_assert(client_streams_in_count > 0);
1392     --client_streams_in_count;
1393   } else {
1394     ink_assert(client_streams_out_count > 0);
1395     --client_streams_out_count;
1396   }
1397   // total_client_streams_count will be decremented in release_stream(), because it's a counter include streams in the process of
1398   // shutting down.
1399 
1400   stream->initiating_close();
1401 
1402   return true;
1403 }
1404 
1405 void
release_stream()1406 Http2ConnectionState::release_stream()
1407 {
1408   REMEMBER(NO_EVENT, this->recursion)
1409 
1410   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
1411   if (this->ua_session) {
1412     ink_assert(this->mutex == ua_session->mutex);
1413 
1414     if (total_client_streams_count == 0) {
1415       if (fini_received) {
1416         ua_session->clear_session_active();
1417 
1418         // We were shutting down, go ahead and terminate the session
1419         // this is a member of Http2ConnectionState and will be freed
1420         // when ua_session is destroyed
1421         ua_session->destroy();
1422 
1423         // Can't do this because we just destroyed right here ^,
1424         // or we can use a local variable to do it.
1425         // ua_session = nullptr;
1426       } else if (shutdown_state == HTTP2_SHUTDOWN_IN_PROGRESS && fini_event == nullptr) {
1427         ua_session->clear_session_active();
1428         fini_event = this_ethread()->schedule_imm_local((Continuation *)this, HTTP2_SESSION_EVENT_FINI);
1429       } else if (ua_session->is_active()) {
1430         // If the number of clients is 0, HTTP2_SESSION_EVENT_FINI is not received or sent, and ua_session is active,
1431         // then mark the connection as inactive
1432         ua_session->clear_session_active();
1433         UnixNetVConnection *vc = static_cast<UnixNetVConnection *>(ua_session->get_netvc());
1434         if (vc && vc->active_timeout_in == 0) {
1435           // With heavy traffic, ua_session could be destroyed. Do not touch ua_session after this.
1436           vc->add_to_keep_alive_queue();
1437         }
1438       } else {
1439         schedule_zombie_event();
1440       }
1441     } else if (fini_received) {
1442       schedule_zombie_event();
1443     }
1444   }
1445 }
1446 
1447 void
update_initial_rwnd(Http2WindowSize new_size)1448 Http2ConnectionState::update_initial_rwnd(Http2WindowSize new_size)
1449 {
1450   // Update stream level window sizes
1451   for (Http2Stream *s = stream_list.head; s; s = static_cast<Http2Stream *>(s->link.next)) {
1452     SCOPED_MUTEX_LOCK(lock, s->mutex, this_ethread());
1453     s->update_initial_rwnd(new_size - (client_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE) - s->client_rwnd()));
1454   }
1455 }
1456 
1457 void
schedule_stream(Http2Stream * stream)1458 Http2ConnectionState::schedule_stream(Http2Stream *stream)
1459 {
1460   Http2StreamDebug(ua_session, stream->get_id(), "Scheduled");
1461 
1462   Http2DependencyTree::Node *node = stream->priority_node;
1463   ink_release_assert(node != nullptr);
1464 
1465   SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
1466   dependency_tree->activate(node);
1467 
1468   if (!_scheduled) {
1469     _scheduled = true;
1470 
1471     SET_HANDLER(&Http2ConnectionState::main_event_handler);
1472     this_ethread()->schedule_imm_local((Continuation *)this, HTTP2_SESSION_EVENT_XMIT);
1473   }
1474 }
1475 
1476 void
send_data_frames_depends_on_priority()1477 Http2ConnectionState::send_data_frames_depends_on_priority()
1478 {
1479   Http2DependencyTree::Node *node = dependency_tree->top();
1480 
1481   // No node to send or no connection level window left
1482   if (node == nullptr || _client_rwnd <= 0) {
1483     return;
1484   }
1485 
1486   Http2Stream *stream = static_cast<Http2Stream *>(node->t);
1487   ink_release_assert(stream != nullptr);
1488   Http2StreamDebug(ua_session, stream->get_id(), "top node, point=%d", node->point);
1489 
1490   size_t len                      = 0;
1491   Http2SendDataFrameResult result = send_a_data_frame(stream, len);
1492 
1493   switch (result) {
1494   case Http2SendDataFrameResult::NO_ERROR: {
1495     // No response body to send
1496     if (len == 0 && !stream->is_write_vio_done()) {
1497       dependency_tree->deactivate(node, len);
1498     } else {
1499       dependency_tree->update(node, len);
1500 
1501       SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
1502       stream->signal_write_event(true);
1503     }
1504     break;
1505   }
1506   case Http2SendDataFrameResult::DONE: {
1507     dependency_tree->deactivate(node, len);
1508     stream->initiating_close();
1509     break;
1510   }
1511   default:
1512     // When no stream level window left, deactivate node once and wait window_update frame
1513     dependency_tree->deactivate(node, len);
1514     break;
1515   }
1516 
1517   this_ethread()->schedule_imm_local((Continuation *)this, HTTP2_SESSION_EVENT_XMIT);
1518   return;
1519 }
1520 
1521 Http2SendDataFrameResult
send_a_data_frame(Http2Stream * stream,size_t & payload_length)1522 Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_length)
1523 {
1524   const ssize_t window_size         = std::min(this->client_rwnd(), stream->client_rwnd());
1525   const size_t buf_len              = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_DATA]);
1526   const size_t write_available_size = std::min(buf_len, static_cast<size_t>(window_size));
1527   payload_length                    = 0;
1528 
1529   uint8_t flags               = 0x00;
1530   IOBufferReader *resp_reader = stream->response_get_data_reader();
1531 
1532   SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
1533 
1534   if (!resp_reader) {
1535     Http2StreamDebug(this->ua_session, stream->get_id(), "couldn't get data reader");
1536     return Http2SendDataFrameResult::ERROR;
1537   }
1538 
1539   if (this->ua_session->write_avail() == 0) {
1540     Http2StreamDebug(this->ua_session, stream->get_id(), "Not write avail");
1541     return Http2SendDataFrameResult::NOT_WRITE_AVAIL;
1542   }
1543 
1544   // Select appropriate payload length
1545   if (resp_reader->is_read_avail_more_than(0)) {
1546     // We only need to check for window size when there is a payload
1547     if (window_size <= 0) {
1548       Http2StreamDebug(this->ua_session, stream->get_id(), "No window");
1549       return Http2SendDataFrameResult::NO_WINDOW;
1550     }
1551 
1552     if (resp_reader->is_read_avail_more_than(write_available_size)) {
1553       payload_length = write_available_size;
1554     } else {
1555       payload_length = resp_reader->read_avail();
1556     }
1557   } else {
1558     payload_length = 0;
1559   }
1560 
1561   // Are we at the end?
1562   // If we return here, we never send the END_STREAM in the case of a early terminating OS.
1563   // OK if there is no body yet. Otherwise continue on to send a DATA frame and delete the stream
1564   if (!stream->is_write_vio_done() && payload_length == 0) {
1565     Http2StreamDebug(this->ua_session, stream->get_id(), "No payload");
1566     return Http2SendDataFrameResult::NO_PAYLOAD;
1567   }
1568 
1569   if (stream->is_write_vio_done() && !resp_reader->is_read_avail_more_than(0)) {
1570     flags |= HTTP2_FLAGS_DATA_END_STREAM;
1571   }
1572 
1573   // Update window size
1574   this->decrement_client_rwnd(payload_length);
1575   stream->decrement_client_rwnd(payload_length);
1576 
1577   // Create frame
1578   Http2StreamDebug(ua_session, stream->get_id(), "Send a DATA frame - client window con: %5zd stream: %5zd payload: %5zd",
1579                    _client_rwnd, stream->client_rwnd(), payload_length);
1580 
1581   Http2DataFrame data(stream->get_id(), flags, resp_reader, payload_length);
1582   this->ua_session->xmit(data);
1583 
1584   stream->update_sent_count(payload_length);
1585 
1586   if (flags & HTTP2_FLAGS_DATA_END_STREAM) {
1587     Http2StreamDebug(ua_session, stream->get_id(), "END_STREAM");
1588     stream->send_end_stream = true;
1589     // Setting to the same state shouldn't be erroneous
1590     stream->change_state(HTTP2_FRAME_TYPE_DATA, flags);
1591 
1592     return Http2SendDataFrameResult::DONE;
1593   }
1594 
1595   return Http2SendDataFrameResult::NO_ERROR;
1596 }
1597 
1598 void
send_data_frames(Http2Stream * stream)1599 Http2ConnectionState::send_data_frames(Http2Stream *stream)
1600 {
1601   // To follow RFC 7540 must not send more frames other than priority on
1602   // a closed stream.  So we return without sending
1603   if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL ||
1604       stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
1605     Http2StreamDebug(this->ua_session, stream->get_id(), "Shutdown half closed local stream");
1606     stream->initiating_close();
1607     return;
1608   }
1609 
1610   size_t len                      = 0;
1611   Http2SendDataFrameResult result = Http2SendDataFrameResult::NO_ERROR;
1612   while (result == Http2SendDataFrameResult::NO_ERROR) {
1613     result = send_a_data_frame(stream, len);
1614 
1615     if (result == Http2SendDataFrameResult::DONE) {
1616       // Delete a stream immediately
1617       // TODO its should not be deleted for a several time to handling
1618       // RST_STREAM and WINDOW_UPDATE.
1619       // See 'closed' state written at [RFC 7540] 5.1.
1620       Http2StreamDebug(this->ua_session, stream->get_id(), "Shutdown stream");
1621       stream->initiating_close();
1622     }
1623   }
1624 
1625   return;
1626 }
1627 
1628 void
send_headers_frame(Http2Stream * stream)1629 Http2ConnectionState::send_headers_frame(Http2Stream *stream)
1630 {
1631   uint8_t *buf                = nullptr;
1632   uint32_t buf_len            = 0;
1633   uint32_t header_blocks_size = 0;
1634   int payload_length          = 0;
1635   uint8_t flags               = 0x00;
1636 
1637   Http2StreamDebug(ua_session, stream->get_id(), "Send HEADERS frame");
1638 
1639   HTTPHdr *resp_hdr = &stream->response_header;
1640   http2_convert_header_from_1_1_to_2(resp_hdr);
1641 
1642   buf_len = resp_hdr->length_get() * 2; // Make it double just in case
1643   buf     = static_cast<uint8_t *>(ats_malloc(buf_len));
1644   if (buf == nullptr) {
1645     return;
1646   }
1647 
1648   stream->mark_milestone(Http2StreamMilestone::START_ENCODE_HEADERS);
1649   Http2ErrorCode result = http2_encode_header_blocks(resp_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle),
1650                                                      client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
1651   if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
1652     ats_free(buf);
1653     return;
1654   }
1655 
1656   // Send a HEADERS frame
1657   if (header_blocks_size <= static_cast<uint32_t>(BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_HEADERS]))) {
1658     payload_length = header_blocks_size;
1659     flags |= HTTP2_FLAGS_HEADERS_END_HEADERS;
1660     if ((resp_hdr->presence(MIME_PRESENCE_CONTENT_LENGTH) && resp_hdr->get_content_length() == 0) ||
1661         (!resp_hdr->expect_final_response() && stream->is_write_vio_done())) {
1662       Http2StreamDebug(ua_session, stream->get_id(), "END_STREAM");
1663       flags |= HTTP2_FLAGS_HEADERS_END_STREAM;
1664       stream->send_end_stream = true;
1665     }
1666     stream->mark_milestone(Http2StreamMilestone::START_TX_HEADERS_FRAMES);
1667   } else {
1668     payload_length = BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_HEADERS]);
1669   }
1670 
1671   // Change stream state
1672   if (!stream->change_state(HTTP2_FRAME_TYPE_HEADERS, flags)) {
1673     this->send_goaway_frame(this->latest_streamid_in, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR);
1674     this->ua_session->set_half_close_local_flag(true);
1675     if (fini_event == nullptr) {
1676       fini_event = this_ethread()->schedule_imm_local((Continuation *)this, HTTP2_SESSION_EVENT_FINI);
1677     }
1678 
1679     ats_free(buf);
1680     return;
1681   }
1682 
1683   Http2HeadersFrame headers(stream->get_id(), flags, buf, payload_length);
1684   this->ua_session->xmit(headers);
1685   uint64_t sent = payload_length;
1686 
1687   // Send CONTINUATION frames
1688   flags = 0;
1689   while (sent < header_blocks_size) {
1690     Http2StreamDebug(ua_session, stream->get_id(), "Send CONTINUATION frame");
1691     payload_length = std::min(static_cast<uint32_t>(BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_CONTINUATION])),
1692                               static_cast<uint32_t>(header_blocks_size - sent));
1693     if (sent + payload_length == header_blocks_size) {
1694       flags |= HTTP2_FLAGS_CONTINUATION_END_HEADERS;
1695     }
1696     stream->change_state(HTTP2_FRAME_TYPE_CONTINUATION, flags);
1697 
1698     Http2ContinuationFrame continuation_frame(stream->get_id(), flags, buf + sent, payload_length);
1699     this->ua_session->xmit(continuation_frame);
1700     sent += payload_length;
1701   }
1702 
1703   ats_free(buf);
1704 }
1705 
1706 bool
send_push_promise_frame(Http2Stream * stream,URL & url,const MIMEField * accept_encoding)1707 Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url, const MIMEField *accept_encoding)
1708 {
1709   uint8_t *buf                = nullptr;
1710   uint32_t buf_len            = 0;
1711   uint32_t header_blocks_size = 0;
1712   int payload_length          = 0;
1713   uint8_t flags               = 0x00;
1714 
1715   if (client_settings.get(HTTP2_SETTINGS_ENABLE_PUSH) == 0) {
1716     return false;
1717   }
1718 
1719   Http2StreamDebug(ua_session, stream->get_id(), "Send PUSH_PROMISE frame");
1720 
1721   HTTPHdr hdr;
1722   ts::PostScript hdr_defer([&]() -> void { hdr.destroy(); });
1723   hdr.create(HTTP_TYPE_REQUEST);
1724   http2_init_pseudo_headers(hdr);
1725   hdr.url_set(&url);
1726   hdr.method_set(HTTP_METHOD_GET, HTTP_LEN_GET);
1727 
1728   if (accept_encoding != nullptr) {
1729     int name_len;
1730     const char *name = accept_encoding->name_get(&name_len);
1731     MIMEField *f     = hdr.field_create(name, name_len);
1732 
1733     int value_len;
1734     const char *value = accept_encoding->value_get(&value_len);
1735     f->value_set(hdr.m_heap, hdr.m_mime, value, value_len);
1736 
1737     hdr.field_attach(f);
1738   }
1739 
1740   http2_convert_header_from_1_1_to_2(&hdr);
1741 
1742   buf_len = hdr.length_get() * 2; // Make it double just in case
1743   buf     = static_cast<uint8_t *>(ats_malloc(buf_len));
1744   if (buf == nullptr) {
1745     return false;
1746   }
1747   Http2ErrorCode result = http2_encode_header_blocks(&hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle),
1748                                                      client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
1749   if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
1750     ats_free(buf);
1751     return false;
1752   }
1753 
1754   // Send a PUSH_PROMISE frame
1755   Http2PushPromise push_promise;
1756   if (header_blocks_size <=
1757       BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_PUSH_PROMISE]) - sizeof(push_promise.promised_streamid)) {
1758     payload_length = header_blocks_size;
1759     flags |= HTTP2_FLAGS_PUSH_PROMISE_END_HEADERS;
1760   } else {
1761     payload_length =
1762       BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_PUSH_PROMISE]) - sizeof(push_promise.promised_streamid);
1763   }
1764 
1765   Http2StreamId id               = this->get_latest_stream_id_out() + 2;
1766   push_promise.promised_streamid = id;
1767 
1768   Http2PushPromiseFrame push_promise_frame(stream->get_id(), flags, push_promise, buf, payload_length);
1769   this->ua_session->xmit(push_promise_frame);
1770   uint64_t sent = payload_length;
1771 
1772   // Send CONTINUATION frames
1773   flags = 0;
1774   while (sent < header_blocks_size) {
1775     Http2StreamDebug(ua_session, stream->get_id(), "Send CONTINUATION frame");
1776     payload_length = std::min(static_cast<uint32_t>(BUFFER_SIZE_FOR_INDEX(buffer_size_index[HTTP2_FRAME_TYPE_CONTINUATION])),
1777                               static_cast<uint32_t>(header_blocks_size - sent));
1778     if (sent + payload_length == header_blocks_size) {
1779       flags |= HTTP2_FLAGS_CONTINUATION_END_HEADERS;
1780     }
1781 
1782     Http2ContinuationFrame continuation(stream->get_id(), flags, buf + sent, payload_length);
1783     this->ua_session->xmit(continuation);
1784     sent += payload_length;
1785   }
1786   ats_free(buf);
1787 
1788   Http2Error error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
1789   stream = this->create_stream(id, error);
1790   if (!stream) {
1791     return false;
1792   }
1793 
1794   SCOPED_MUTEX_LOCK(stream_lock, stream->mutex, this_ethread());
1795   if (Http2::stream_priority_enabled) {
1796     Http2DependencyTree::Node *node = this->dependency_tree->find(id);
1797     if (node != nullptr) {
1798       stream->priority_node = node;
1799     } else {
1800       Http2StreamDebug(this->ua_session, id, "PRIORITY - dep: %d, weight: %d, excl: %d, tree size: %d",
1801                        HTTP2_PRIORITY_DEFAULT_STREAM_DEPENDENCY, HTTP2_PRIORITY_DEFAULT_WEIGHT, false,
1802                        this->dependency_tree->size());
1803 
1804       stream->priority_node =
1805         this->dependency_tree->add(HTTP2_PRIORITY_DEFAULT_STREAM_DEPENDENCY, id, HTTP2_PRIORITY_DEFAULT_WEIGHT, false, stream);
1806     }
1807   }
1808   stream->change_state(HTTP2_FRAME_TYPE_PUSH_PROMISE, HTTP2_FLAGS_PUSH_PROMISE_END_HEADERS);
1809   stream->set_request_headers(hdr);
1810   stream->new_transaction();
1811   stream->send_request(*this);
1812 
1813   return true;
1814 }
1815 
1816 void
send_rst_stream_frame(Http2StreamId id,Http2ErrorCode ec)1817 Http2ConnectionState::send_rst_stream_frame(Http2StreamId id, Http2ErrorCode ec)
1818 {
1819   Http2StreamDebug(ua_session, id, "Send RST_STREAM frame");
1820 
1821   if (ec != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
1822     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_STREAM_ERRORS_COUNT, this_ethread());
1823     ++stream_error_count;
1824   }
1825 
1826   // change state to closed
1827   Http2Stream *stream = find_stream(id);
1828   if (stream != nullptr) {
1829     stream->set_tx_error_code({ProxyErrorClass::TXN, static_cast<uint32_t>(ec)});
1830     if (!stream->change_state(HTTP2_FRAME_TYPE_RST_STREAM, 0)) {
1831       this->send_goaway_frame(this->latest_streamid_in, Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR);
1832       this->ua_session->set_half_close_local_flag(true);
1833       if (fini_event == nullptr) {
1834         fini_event = this_ethread()->schedule_imm_local((Continuation *)this, HTTP2_SESSION_EVENT_FINI);
1835       }
1836 
1837       return;
1838     }
1839   }
1840 
1841   Http2RstStreamFrame rst_stream(id, static_cast<uint32_t>(ec));
1842   this->ua_session->xmit(rst_stream);
1843 }
1844 
1845 void
send_settings_frame(const Http2ConnectionSettings & new_settings)1846 Http2ConnectionState::send_settings_frame(const Http2ConnectionSettings &new_settings)
1847 {
1848   const Http2StreamId stream_id = 0;
1849 
1850   Http2StreamDebug(ua_session, stream_id, "Send SETTINGS frame");
1851 
1852   Http2SettingsParameter params[HTTP2_SETTINGS_MAX];
1853   size_t params_size = 0;
1854 
1855   for (int i = HTTP2_SETTINGS_HEADER_TABLE_SIZE; i < HTTP2_SETTINGS_MAX; ++i) {
1856     Http2SettingsIdentifier id = static_cast<Http2SettingsIdentifier>(i);
1857     unsigned settings_value    = new_settings.get(id);
1858 
1859     // Send only difference
1860     if (settings_value != server_settings.get(id)) {
1861       Http2StreamDebug(ua_session, stream_id, "  %s : %u", Http2DebugNames::get_settings_param_name(id), settings_value);
1862 
1863       params[params_size++] = {static_cast<uint16_t>(id), settings_value};
1864 
1865       // Update current settings
1866       server_settings.set(id, new_settings.get(id));
1867     }
1868   }
1869 
1870   Http2SettingsFrame settings(stream_id, HTTP2_FRAME_NO_FLAG, params, params_size);
1871   this->ua_session->xmit(settings);
1872 }
1873 
1874 void
send_ping_frame(Http2StreamId id,uint8_t flag,const uint8_t * opaque_data)1875 Http2ConnectionState::send_ping_frame(Http2StreamId id, uint8_t flag, const uint8_t *opaque_data)
1876 {
1877   Http2StreamDebug(ua_session, id, "Send PING frame");
1878 
1879   Http2PingFrame ping(id, flag, opaque_data);
1880   this->ua_session->xmit(ping);
1881 }
1882 
1883 // As for gracefull shutdown, TS should process outstanding stream as long as possible.
1884 // As for signal connection error, TS should close connection immediately.
1885 void
send_goaway_frame(Http2StreamId id,Http2ErrorCode ec)1886 Http2ConnectionState::send_goaway_frame(Http2StreamId id, Http2ErrorCode ec)
1887 {
1888   ink_assert(this->ua_session != nullptr);
1889 
1890   Http2ConDebug(ua_session, "Send GOAWAY frame, last_stream_id: %d", id);
1891 
1892   if (ec != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
1893     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_CONNECTION_ERRORS_COUNT, this_ethread());
1894   }
1895 
1896   this->tx_error_code = {ProxyErrorClass::SSN, static_cast<uint32_t>(ec)};
1897 
1898   Http2Goaway goaway;
1899   goaway.last_streamid = id;
1900   goaway.error_code    = ec;
1901 
1902   Http2GoawayFrame frame(goaway);
1903   this->ua_session->xmit(frame);
1904 }
1905 
1906 void
send_window_update_frame(Http2StreamId id,uint32_t size)1907 Http2ConnectionState::send_window_update_frame(Http2StreamId id, uint32_t size)
1908 {
1909   Http2StreamDebug(ua_session, id, "Send WINDOW_UPDATE frame: size=%" PRIu32, size);
1910 
1911   // Create WINDOW_UPDATE frame
1912   Http2WindowUpdateFrame window_update(id, size);
1913   this->ua_session->xmit(window_update);
1914 }
1915 
1916 void
increment_received_settings_count(uint32_t count)1917 Http2ConnectionState::increment_received_settings_count(uint32_t count)
1918 {
1919   this->_received_settings_counter.increment(count);
1920 }
1921 
1922 uint32_t
get_received_settings_count()1923 Http2ConnectionState::get_received_settings_count()
1924 {
1925   return this->_received_settings_counter.get_count();
1926 }
1927 
1928 void
increment_received_settings_frame_count()1929 Http2ConnectionState::increment_received_settings_frame_count()
1930 {
1931   this->_received_settings_frame_counter.increment();
1932 }
1933 
1934 uint32_t
get_received_settings_frame_count()1935 Http2ConnectionState::get_received_settings_frame_count()
1936 {
1937   return this->_received_settings_frame_counter.get_count();
1938 }
1939 
1940 void
increment_received_ping_frame_count()1941 Http2ConnectionState::increment_received_ping_frame_count()
1942 {
1943   this->_received_ping_frame_counter.increment();
1944 }
1945 
1946 uint32_t
get_received_ping_frame_count()1947 Http2ConnectionState::get_received_ping_frame_count()
1948 {
1949   return this->_received_ping_frame_counter.get_count();
1950 }
1951 
1952 void
increment_received_priority_frame_count()1953 Http2ConnectionState::increment_received_priority_frame_count()
1954 {
1955   this->_received_priority_frame_counter.increment();
1956 }
1957 
1958 uint32_t
get_received_priority_frame_count()1959 Http2ConnectionState::get_received_priority_frame_count()
1960 {
1961   return this->_received_priority_frame_counter.get_count();
1962 }
1963 
1964 // Return min_concurrent_streams_in when current client streams number is larger than max_active_streams_in.
1965 // Main purpose of this is preventing DDoS Attacks.
1966 unsigned
_adjust_concurrent_stream()1967 Http2ConnectionState::_adjust_concurrent_stream()
1968 {
1969   if (Http2::max_active_streams_in == 0) {
1970     // Throttling down is disabled.
1971     return Http2::max_concurrent_streams_in;
1972   }
1973 
1974   int64_t current_client_streams = 0;
1975   RecGetRawStatSum(http2_rsb, HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT, &current_client_streams);
1976 
1977   Http2ConDebug(ua_session, "current client streams: %" PRId64, current_client_streams);
1978 
1979   if (current_client_streams >= Http2::max_active_streams_in) {
1980     if (!Http2::throttling) {
1981       Warning("too many streams: %" PRId64 ", reduce SETTINGS_MAX_CONCURRENT_STREAMS to %d", current_client_streams,
1982               Http2::min_concurrent_streams_in);
1983       Http2::throttling = true;
1984     }
1985 
1986     return Http2::min_concurrent_streams_in;
1987   } else {
1988     if (Http2::throttling) {
1989       Note("revert SETTINGS_MAX_CONCURRENT_STREAMS to %d", Http2::max_concurrent_streams_in);
1990       Http2::throttling = false;
1991     }
1992   }
1993 
1994   return Http2::max_concurrent_streams_in;
1995 }
1996 
1997 ssize_t
client_rwnd() const1998 Http2ConnectionState::client_rwnd() const
1999 {
2000   return this->_client_rwnd;
2001 }
2002 
2003 Http2ErrorCode
increment_client_rwnd(size_t amount)2004 Http2ConnectionState::increment_client_rwnd(size_t amount)
2005 {
2006   this->_client_rwnd += amount;
2007 
2008   this->_recent_rwnd_increment[this->_recent_rwnd_increment_index] = amount;
2009   ++this->_recent_rwnd_increment_index;
2010   this->_recent_rwnd_increment_index %= this->_recent_rwnd_increment.size();
2011   double sum = std::accumulate(this->_recent_rwnd_increment.begin(), this->_recent_rwnd_increment.end(), 0.0);
2012   double avg = sum / this->_recent_rwnd_increment.size();
2013   if (avg < Http2::min_avg_window_update) {
2014     HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE, this_ethread());
2015     return Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM;
2016   }
2017   return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
2018 }
2019 
2020 Http2ErrorCode
decrement_client_rwnd(size_t amount)2021 Http2ConnectionState::decrement_client_rwnd(size_t amount)
2022 {
2023   this->_client_rwnd -= amount;
2024   return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
2025 }
2026 
2027 ssize_t
server_rwnd() const2028 Http2ConnectionState::server_rwnd() const
2029 {
2030   return this->_server_rwnd;
2031 }
2032 
2033 Http2ErrorCode
increment_server_rwnd(size_t amount)2034 Http2ConnectionState::increment_server_rwnd(size_t amount)
2035 {
2036   this->_server_rwnd += amount;
2037   return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
2038 }
2039 
2040 Http2ErrorCode
decrement_server_rwnd(size_t amount)2041 Http2ConnectionState::decrement_server_rwnd(size_t amount)
2042 {
2043   this->_server_rwnd -= amount;
2044   return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
2045 }
2046