1 /** @file
2  *
3  *  Fundamental HTTP/2 protocol definitions and parsers.
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 "HTTP2.h"
25 #include "HPACK.h"
26 
27 #include "tscore/ink_assert.h"
28 #include "tscpp/util/LocalBuffer.h"
29 
30 #include "records/P_RecCore.h"
31 #include "records/P_RecProcess.h"
32 
33 const char *const HTTP2_CONNECTION_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
34 
35 // Constant strings for pseudo headers
36 const char *HTTP2_VALUE_SCHEME    = ":scheme";
37 const char *HTTP2_VALUE_METHOD    = ":method";
38 const char *HTTP2_VALUE_AUTHORITY = ":authority";
39 const char *HTTP2_VALUE_PATH      = ":path";
40 const char *HTTP2_VALUE_STATUS    = ":status";
41 
42 const unsigned HTTP2_LEN_SCHEME    = countof(":scheme") - 1;
43 const unsigned HTTP2_LEN_METHOD    = countof(":method") - 1;
44 const unsigned HTTP2_LEN_AUTHORITY = countof(":authority") - 1;
45 const unsigned HTTP2_LEN_PATH      = countof(":path") - 1;
46 const unsigned HTTP2_LEN_STATUS    = countof(":status") - 1;
47 
48 static size_t HTTP2_LEN_STATUS_VALUE_STR         = 3;
49 static const uint32_t HTTP2_MAX_TABLE_SIZE_LIMIT = 64 * 1024;
50 
51 namespace
52 {
53 struct Http2HeaderName {
54   const char *name = nullptr;
55   int name_len     = 0;
56 };
57 
58 Http2HeaderName http2_connection_specific_headers[5] = {};
59 } // namespace
60 
61 // Statistics
62 RecRawStatBlock *http2_rsb;
63 static const char *const HTTP2_STAT_CURRENT_CLIENT_CONNECTION_NAME        = "proxy.process.http2.current_client_connections";
64 static const char *const HTTP2_STAT_CURRENT_ACTIVE_CLIENT_CONNECTION_NAME = "proxy.process.http2.current_active_client_connections";
65 static const char *const HTTP2_STAT_CURRENT_CLIENT_STREAM_NAME            = "proxy.process.http2.current_client_streams";
66 static const char *const HTTP2_STAT_TOTAL_CLIENT_STREAM_NAME              = "proxy.process.http2.total_client_streams";
67 static const char *const HTTP2_STAT_TOTAL_TRANSACTIONS_TIME_NAME          = "proxy.process.http2.total_transactions_time";
68 static const char *const HTTP2_STAT_TOTAL_CLIENT_CONNECTION_NAME          = "proxy.process.http2.total_client_connections";
69 static const char *const HTTP2_STAT_CONNECTION_ERRORS_NAME                = "proxy.process.http2.connection_errors";
70 static const char *const HTTP2_STAT_STREAM_ERRORS_NAME                    = "proxy.process.http2.stream_errors";
71 static const char *const HTTP2_STAT_SESSION_DIE_DEFAULT_NAME              = "proxy.process.http2.session_die_default";
72 static const char *const HTTP2_STAT_SESSION_DIE_OTHER_NAME                = "proxy.process.http2.session_die_other";
73 static const char *const HTTP2_STAT_SESSION_DIE_ACTIVE_NAME               = "proxy.process.http2.session_die_active";
74 static const char *const HTTP2_STAT_SESSION_DIE_INACTIVE_NAME             = "proxy.process.http2.session_die_inactive";
75 static const char *const HTTP2_STAT_SESSION_DIE_EOS_NAME                  = "proxy.process.http2.session_die_eos";
76 static const char *const HTTP2_STAT_SESSION_DIE_ERROR_NAME                = "proxy.process.http2.session_die_error";
77 static const char *const HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE_NAME      = "proxy.process.http2.session_die_high_error_rate";
78 static const char *const HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED_NAME  = "proxy.process.http2.max_settings_per_frame_exceeded";
79 static const char *const HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED_NAME = "proxy.process.http2.max_settings_per_minute_exceeded";
80 static const char *const HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED_NAME =
81   "proxy.process.http2.max_settings_frames_per_minute_exceeded";
82 static const char *const HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED_NAME =
83   "proxy.process.http2.max_ping_frames_per_minute_exceeded";
84 static const char *const HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME =
85   "proxy.process.http2.max_priority_frames_per_minute_exceeded";
86 static const char *const HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME = "proxy.process.http2.insufficient_avg_window_update";
87 
88 union byte_pointer {
byte_pointer(void * p)89   byte_pointer(void *p) : ptr(p) {}
90   void *ptr;
91   uint8_t *u8;
92   uint16_t *u16;
93   uint32_t *u32;
94 };
95 
96 template <typename T> union byte_addressable_value {
97   uint8_t bytes[sizeof(T)];
98   T value;
99 };
100 
101 static void
write_and_advance(byte_pointer & dst,const uint8_t * src,size_t length)102 write_and_advance(byte_pointer &dst, const uint8_t *src, size_t length)
103 {
104   memcpy(dst.u8, src, length);
105   dst.u8 += length;
106 }
107 
108 static void
write_and_advance(byte_pointer & dst,uint32_t src)109 write_and_advance(byte_pointer &dst, uint32_t src)
110 {
111   byte_addressable_value<uint32_t> pval;
112 
113   // cppcheck-suppress unreadVariable ; it's an union and be read as pval.bytes
114   pval.value = htonl(src);
115   memcpy(dst.u8, pval.bytes, sizeof(pval.bytes));
116   dst.u8 += sizeof(pval.bytes);
117 }
118 
119 static void
write_and_advance(byte_pointer & dst,uint16_t src)120 write_and_advance(byte_pointer &dst, uint16_t src)
121 {
122   byte_addressable_value<uint16_t> pval;
123 
124   // cppcheck-suppress unreadVariable ; it's an union and be read as pval.bytes
125   pval.value = htons(src);
126   memcpy(dst.u8, pval.bytes, sizeof(pval.bytes));
127   dst.u8 += sizeof(pval.bytes);
128 }
129 
130 static void
write_and_advance(byte_pointer & dst,uint8_t src)131 write_and_advance(byte_pointer &dst, uint8_t src)
132 {
133   *dst.u8 = src;
134   dst.u8++;
135 }
136 
137 template <unsigned N>
138 static void
memcpy_and_advance(uint8_t (& dst)[N],byte_pointer & src)139 memcpy_and_advance(uint8_t (&dst)[N], byte_pointer &src)
140 {
141   memcpy(dst, src.u8, N);
142   src.u8 += N;
143 }
144 
145 static void
memcpy_and_advance(uint8_t (& dst),byte_pointer & src)146 memcpy_and_advance(uint8_t(&dst), byte_pointer &src)
147 {
148   dst = *src.u8;
149   ++src.u8;
150 }
151 
152 bool
http2_frame_header_is_valid(const Http2FrameHeader & hdr,unsigned max_frame_size)153 http2_frame_header_is_valid(const Http2FrameHeader &hdr, unsigned max_frame_size)
154 {
155   // 6.1 If a DATA frame is received whose stream identifier field is 0x0, the recipient MUST
156   // respond with a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
157   if (hdr.type == HTTP2_FRAME_TYPE_DATA && hdr.streamid == 0) {
158     return false;
159   }
160 
161   return true;
162 }
163 
164 bool
http2_settings_parameter_is_valid(const Http2SettingsParameter & param)165 http2_settings_parameter_is_valid(const Http2SettingsParameter &param)
166 {
167   // Static maximum values for Settings parameters.
168   static const uint32_t settings_max[HTTP2_SETTINGS_MAX] = {
169     0,
170     UINT_MAX,              // HTTP2_SETTINGS_HEADER_TABLE_SIZE
171     1,                     // HTTP2_SETTINGS_ENABLE_PUSH
172     UINT_MAX,              // HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
173     HTTP2_MAX_WINDOW_SIZE, // HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
174     16777215,              // HTTP2_SETTINGS_MAX_FRAME_SIZE
175     UINT_MAX,              // HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE
176   };
177 
178   if (param.id == 0 || param.id >= HTTP2_SETTINGS_MAX) {
179     // Do nothing - 6.5.2 Unsupported parameters MUST be ignored
180     return true;
181   }
182 
183   if (param.value > settings_max[param.id]) {
184     return false;
185   }
186 
187   if (param.id == HTTP2_SETTINGS_ENABLE_PUSH && param.value != 0 && param.value != 1) {
188     return false;
189   }
190 
191   if (param.id == HTTP2_SETTINGS_MAX_FRAME_SIZE && (param.value < (1 << 14) || param.value > (1 << 24) - 1)) {
192     return false;
193   }
194 
195   return true;
196 }
197 
198 // 4.1.  Frame Format
199 //
200 //  0                   1                   2                   3
201 //  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
202 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
203 // |                 Length (24)                   |
204 // +---------------+---------------+---------------+
205 // |   Type (8)    |   Flags (8)   |
206 // +-+-+-----------+---------------+-------------------------------+
207 // |R|                 Stream Identifier (31)                      |
208 // +=+=============================================================+
209 // |                   Frame Payload (0...)                      ...
210 // +---------------------------------------------------------------+
211 
212 bool
http2_parse_frame_header(IOVec iov,Http2FrameHeader & hdr)213 http2_parse_frame_header(IOVec iov, Http2FrameHeader &hdr)
214 {
215   byte_pointer ptr(iov.iov_base);
216   byte_addressable_value<uint32_t> length_and_type;
217   byte_addressable_value<uint32_t> streamid;
218 
219   if (unlikely(iov.iov_len < HTTP2_FRAME_HEADER_LEN)) {
220     return false;
221   }
222 
223   memcpy_and_advance(length_and_type.bytes, ptr);
224   memcpy_and_advance(hdr.flags, ptr);
225   memcpy_and_advance(streamid.bytes, ptr);
226 
227   hdr.length = ntohl(length_and_type.value) >> 8;
228   hdr.type   = ntohl(length_and_type.value) & 0xff;
229   streamid.bytes[0] &= 0x7f; // Clear the high reserved bit
230   hdr.streamid = ntohl(streamid.value);
231 
232   return true;
233 }
234 
235 bool
http2_write_frame_header(const Http2FrameHeader & hdr,IOVec iov)236 http2_write_frame_header(const Http2FrameHeader &hdr, IOVec iov)
237 {
238   byte_pointer ptr(iov.iov_base);
239 
240   if (unlikely(iov.iov_len < HTTP2_FRAME_HEADER_LEN)) {
241     return false;
242   }
243 
244   byte_addressable_value<uint32_t> length;
245   // cppcheck-suppress unreadVariable ; it's an union and be read as pval.bytes
246   length.value = htonl(hdr.length);
247   // MSB length.bytes[0] is unused.
248   write_and_advance(ptr, length.bytes[1]);
249   write_and_advance(ptr, length.bytes[2]);
250   write_and_advance(ptr, length.bytes[3]);
251 
252   write_and_advance(ptr, hdr.type);
253   write_and_advance(ptr, hdr.flags);
254   write_and_advance(ptr, hdr.streamid);
255 
256   return true;
257 }
258 
259 bool
http2_write_rst_stream(uint32_t error_code,IOVec iov)260 http2_write_rst_stream(uint32_t error_code, IOVec iov)
261 {
262   byte_pointer ptr(iov.iov_base);
263 
264   write_and_advance(ptr, error_code);
265 
266   return true;
267 }
268 
269 bool
http2_write_settings(const Http2SettingsParameter & param,const IOVec & iov)270 http2_write_settings(const Http2SettingsParameter &param, const IOVec &iov)
271 {
272   byte_pointer ptr(iov.iov_base);
273 
274   if (unlikely(iov.iov_len < HTTP2_SETTINGS_PARAMETER_LEN)) {
275     return false;
276   }
277 
278   write_and_advance(ptr, param.id);
279   write_and_advance(ptr, param.value);
280 
281   return true;
282 }
283 
284 bool
http2_write_ping(const uint8_t * opaque_data,IOVec iov)285 http2_write_ping(const uint8_t *opaque_data, IOVec iov)
286 {
287   byte_pointer ptr(iov.iov_base);
288 
289   if (unlikely(iov.iov_len < HTTP2_PING_LEN)) {
290     return false;
291   }
292 
293   write_and_advance(ptr, opaque_data, HTTP2_PING_LEN);
294 
295   return true;
296 }
297 
298 bool
http2_write_goaway(const Http2Goaway & goaway,IOVec iov)299 http2_write_goaway(const Http2Goaway &goaway, IOVec iov)
300 {
301   byte_pointer ptr(iov.iov_base);
302 
303   if (unlikely(iov.iov_len < HTTP2_GOAWAY_LEN)) {
304     return false;
305   }
306 
307   write_and_advance(ptr, goaway.last_streamid);
308   write_and_advance(ptr, static_cast<uint32_t>(goaway.error_code));
309 
310   return true;
311 }
312 
313 bool
http2_write_window_update(const uint32_t new_size,const IOVec & iov)314 http2_write_window_update(const uint32_t new_size, const IOVec &iov)
315 {
316   byte_pointer ptr(iov.iov_base);
317   write_and_advance(ptr, new_size);
318 
319   return true;
320 }
321 
322 bool
http2_write_push_promise(const Http2PushPromise & push_promise,const uint8_t * src,size_t length,const IOVec & iov)323 http2_write_push_promise(const Http2PushPromise &push_promise, const uint8_t *src, size_t length, const IOVec &iov)
324 {
325   byte_pointer ptr(iov.iov_base);
326   write_and_advance(ptr, push_promise.promised_streamid);
327   write_and_advance(ptr, src, length);
328   return true;
329 }
330 
331 bool
http2_parse_headers_parameter(IOVec iov,Http2HeadersParameter & params)332 http2_parse_headers_parameter(IOVec iov, Http2HeadersParameter &params)
333 {
334   byte_pointer ptr(iov.iov_base);
335   memcpy_and_advance(params.pad_length, ptr);
336 
337   return true;
338 }
339 
340 bool
http2_parse_priority_parameter(IOVec iov,Http2Priority & priority)341 http2_parse_priority_parameter(IOVec iov, Http2Priority &priority)
342 {
343   byte_pointer ptr(iov.iov_base);
344   byte_addressable_value<uint32_t> dependency;
345 
346   memcpy_and_advance(dependency.bytes, ptr);
347 
348   priority.exclusive_flag = dependency.bytes[0] & 0x80;
349 
350   dependency.bytes[0] &= 0x7f; // Clear the highest bit for exclusive flag
351   priority.stream_dependency = ntohl(dependency.value);
352 
353   memcpy_and_advance(priority.weight, ptr);
354 
355   return true;
356 }
357 
358 bool
http2_parse_rst_stream(IOVec iov,Http2RstStream & rst_stream)359 http2_parse_rst_stream(IOVec iov, Http2RstStream &rst_stream)
360 {
361   byte_pointer ptr(iov.iov_base);
362   byte_addressable_value<uint32_t> ec;
363 
364   memcpy_and_advance(ec.bytes, ptr);
365 
366   rst_stream.error_code = ntohl(ec.value);
367 
368   return true;
369 }
370 
371 bool
http2_parse_settings_parameter(IOVec iov,Http2SettingsParameter & param)372 http2_parse_settings_parameter(IOVec iov, Http2SettingsParameter &param)
373 {
374   byte_pointer ptr(iov.iov_base);
375   byte_addressable_value<uint16_t> pid;
376   byte_addressable_value<uint32_t> pval;
377 
378   if (unlikely(iov.iov_len < HTTP2_SETTINGS_PARAMETER_LEN)) {
379     return false;
380   }
381 
382   memcpy_and_advance(pid.bytes, ptr);
383   memcpy_and_advance(pval.bytes, ptr);
384 
385   param.id    = ntohs(pid.value);
386   param.value = ntohl(pval.value);
387 
388   return true;
389 }
390 
391 bool
http2_parse_goaway(IOVec iov,Http2Goaway & goaway)392 http2_parse_goaway(IOVec iov, Http2Goaway &goaway)
393 {
394   byte_pointer ptr(iov.iov_base);
395   byte_addressable_value<uint32_t> sid;
396   byte_addressable_value<uint32_t> ec;
397 
398   memcpy_and_advance(sid.bytes, ptr);
399   memcpy_and_advance(ec.bytes, ptr);
400 
401   goaway.last_streamid = ntohl(sid.value);
402   goaway.error_code    = static_cast<Http2ErrorCode>(ntohl(ec.value));
403   return true;
404 }
405 
406 bool
http2_parse_window_update(IOVec iov,uint32_t & size)407 http2_parse_window_update(IOVec iov, uint32_t &size)
408 {
409   byte_pointer ptr(iov.iov_base);
410   byte_addressable_value<uint32_t> s;
411 
412   memcpy_and_advance(s.bytes, ptr);
413 
414   size = ntohl(s.value);
415 
416   return true;
417 }
418 
419 ParseResult
http2_convert_header_from_2_to_1_1(HTTPHdr * headers)420 http2_convert_header_from_2_to_1_1(HTTPHdr *headers)
421 {
422   ink_assert(http_hdr_type_get(headers->m_http) != HTTP_TYPE_UNKNOWN);
423 
424   // HTTP Version
425   headers->version_set(HTTPVersion(1, 1));
426 
427   if (http_hdr_type_get(headers->m_http) == HTTP_TYPE_REQUEST) {
428     // :scheme
429     if (MIMEField *field = headers->field_find(HTTP2_VALUE_SCHEME, HTTP2_LEN_SCHEME); field != nullptr && field->value_is_valid()) {
430       int scheme_len;
431       const char *scheme = field->value_get(&scheme_len);
432 
433       int scheme_wks_idx = hdrtoken_tokenize(scheme, scheme_len);
434       url_scheme_set(headers->m_heap, headers->m_http->u.req.m_url_impl, scheme, scheme_wks_idx, scheme_len, true);
435 
436       headers->field_delete(field);
437     } else {
438       return PARSE_RESULT_ERROR;
439     }
440 
441     // :authority
442     if (MIMEField *field = headers->field_find(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY);
443         field != nullptr && field->value_is_valid()) {
444       int authority_len;
445       const char *authority = field->value_get(&authority_len);
446 
447       url_host_set(headers->m_heap, headers->m_http->u.req.m_url_impl, authority, authority_len, true);
448 
449       headers->field_delete(field);
450     } else {
451       return PARSE_RESULT_ERROR;
452     }
453 
454     // :path
455     if (MIMEField *field = headers->field_find(HTTP2_VALUE_PATH, HTTP2_LEN_PATH); field != nullptr && field->value_is_valid()) {
456       int path_len;
457       const char *path = field->value_get(&path_len);
458 
459       // cut first '/' if there, because `url_print()` add '/' before printing path
460       if (path_len >= 1 && path[0] == '/') {
461         ++path;
462         --path_len;
463       }
464 
465       url_path_set(headers->m_heap, headers->m_http->u.req.m_url_impl, path, path_len, true);
466 
467       headers->field_delete(field);
468     } else {
469       return PARSE_RESULT_ERROR;
470     }
471 
472     // :method
473     if (MIMEField *field = headers->field_find(HTTP2_VALUE_METHOD, HTTP2_LEN_METHOD); field != nullptr && field->value_is_valid()) {
474       int method_len;
475       const char *method = field->value_get(&method_len);
476 
477       headers->method_set(method, method_len);
478       headers->field_delete(field);
479     } else {
480       return PARSE_RESULT_ERROR;
481     }
482 
483     // Combine Cookie headers ([RFC 7540] 8.1.2.5.)
484     if (MIMEField *field = headers->field_find(MIME_FIELD_COOKIE, MIME_LEN_COOKIE); field != nullptr) {
485       headers->field_combine_dups(field, true, ';');
486     }
487   } else {
488     // Set status from :status
489     if (MIMEField *field = headers->field_find(HTTP2_VALUE_STATUS, HTTP2_LEN_STATUS); field != nullptr) {
490       int status_len;
491       const char *status = field->value_get(&status_len);
492 
493       headers->status_set(http_parse_status(status, status + status_len));
494       headers->field_delete(field);
495     } else {
496       return PARSE_RESULT_ERROR;
497     }
498   }
499 
500   // Check validity of all names and values
501   MIMEFieldIter iter;
502   for (auto *mf = headers->iter_get_first(&iter); mf != nullptr; mf = headers->iter_get_next(&iter)) {
503     if (!mf->name_is_valid() || !mf->value_is_valid()) {
504       return PARSE_RESULT_ERROR;
505     }
506   }
507 
508   return PARSE_RESULT_DONE;
509 }
510 
511 /**
512   Initialize HTTPHdr for HTTP/2
513 
514   Reserve HTTP/2 Pseudo-Header Fields in front of HTTPHdr. Value of these header fields will be set by
515   `http2_convert_header_from_1_1_to_2()`. When a HTTPHdr for HTTP/2 headers is created, this should be called immediately.
516   Because all pseudo-header fields MUST appear in the header block before regular header fields.
517  */
518 void
http2_init_pseudo_headers(HTTPHdr & hdr)519 http2_init_pseudo_headers(HTTPHdr &hdr)
520 {
521   switch (http_hdr_type_get(hdr.m_http)) {
522   case HTTP_TYPE_REQUEST: {
523     MIMEField *method = hdr.field_create(HTTP2_VALUE_METHOD, HTTP2_LEN_METHOD);
524     hdr.field_attach(method);
525 
526     MIMEField *scheme = hdr.field_create(HTTP2_VALUE_SCHEME, HTTP2_LEN_SCHEME);
527     hdr.field_attach(scheme);
528 
529     MIMEField *authority = hdr.field_create(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY);
530     hdr.field_attach(authority);
531 
532     MIMEField *path = hdr.field_create(HTTP2_VALUE_PATH, HTTP2_LEN_PATH);
533     hdr.field_attach(path);
534 
535     break;
536   }
537   case HTTP_TYPE_RESPONSE: {
538     MIMEField *status = hdr.field_create(HTTP2_VALUE_STATUS, HTTP2_LEN_STATUS);
539     hdr.field_attach(status);
540 
541     break;
542   }
543   default:
544     ink_abort("HTTP_TYPE_UNKNOWN");
545   }
546 }
547 
548 /**
549   Convert HTTP/1.1 HTTPHdr to HTTP/2
550 
551   Assuming HTTP/2 Pseudo-Header Fields are reserved by `http2_init_pseudo_headers()`.
552  */
553 ParseResult
http2_convert_header_from_1_1_to_2(HTTPHdr * headers)554 http2_convert_header_from_1_1_to_2(HTTPHdr *headers)
555 {
556   switch (http_hdr_type_get(headers->m_http)) {
557   case HTTP_TYPE_REQUEST: {
558     // :method
559     if (MIMEField *field = headers->field_find(HTTP2_VALUE_METHOD, HTTP2_LEN_METHOD); field != nullptr) {
560       int value_len;
561       const char *value = headers->method_get(&value_len);
562 
563       field->value_set(headers->m_heap, headers->m_mime, value, value_len);
564     } else {
565       ink_abort("initialize HTTP/2 pseudo-headers");
566       return PARSE_RESULT_ERROR;
567     }
568 
569     // :scheme
570     if (MIMEField *field = headers->field_find(HTTP2_VALUE_SCHEME, HTTP2_LEN_SCHEME); field != nullptr) {
571       int value_len;
572       const char *value = headers->scheme_get(&value_len);
573 
574       if (value != nullptr) {
575         field->value_set(headers->m_heap, headers->m_mime, value, value_len);
576       } else {
577         field->value_set(headers->m_heap, headers->m_mime, URL_SCHEME_HTTPS, URL_LEN_HTTPS);
578       }
579     } else {
580       ink_abort("initialize HTTP/2 pseudo-headers");
581       return PARSE_RESULT_ERROR;
582     }
583 
584     // :authority
585     if (MIMEField *field = headers->field_find(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY); field != nullptr) {
586       int value_len;
587       const char *value = headers->host_get(&value_len);
588 
589       if (headers->is_port_in_header()) {
590         int port = headers->port_get();
591         ts::LocalBuffer<char> buf(value_len + 8);
592         char *host_and_port = buf.data();
593         value_len           = snprintf(host_and_port, value_len + 8, "%.*s:%d", value_len, value, port);
594 
595         field->value_set(headers->m_heap, headers->m_mime, host_and_port, value_len);
596       } else {
597         field->value_set(headers->m_heap, headers->m_mime, value, value_len);
598       }
599     } else {
600       ink_abort("initialize HTTP/2 pseudo-headers");
601       return PARSE_RESULT_ERROR;
602     }
603 
604     // :path
605     if (MIMEField *field = headers->field_find(HTTP2_VALUE_PATH, HTTP2_LEN_PATH); field != nullptr) {
606       int value_len;
607       const char *value = headers->path_get(&value_len);
608 
609       ts::LocalBuffer<char> buf(value_len + 1);
610       char *path = buf.data();
611       path[0]    = '/';
612       memcpy(path + 1, value, value_len);
613 
614       field->value_set(headers->m_heap, headers->m_mime, path, value_len + 1);
615     } else {
616       ink_abort("initialize HTTP/2 pseudo-headers");
617       return PARSE_RESULT_ERROR;
618     }
619 
620     // TODO: remove host/Host header
621     // [RFC 7540] 8.1.2.3. Clients that generate HTTP/2 requests directly SHOULD use the ":authority" pseudo-header field instead
622     // of the Host header field.
623 
624     break;
625   }
626   case HTTP_TYPE_RESPONSE: {
627     // :status
628     if (MIMEField *field = headers->field_find(HTTP2_VALUE_STATUS, HTTP2_LEN_STATUS); field != nullptr) {
629       // ink_small_itoa() requires 5+ buffer length
630       char status_str[HTTP2_LEN_STATUS_VALUE_STR + 3];
631       mime_format_int(status_str, headers->status_get(), sizeof(status_str));
632 
633       field->value_set(headers->m_heap, headers->m_mime, status_str, HTTP2_LEN_STATUS_VALUE_STR);
634     } else {
635       ink_abort("initialize HTTP/2 pseudo-headers");
636       return PARSE_RESULT_ERROR;
637     }
638     break;
639   }
640   default:
641     ink_abort("HTTP_TYPE_UNKNOWN");
642   }
643 
644   // Intermediaries SHOULD remove connection-specific header fields.
645   for (auto &h : http2_connection_specific_headers) {
646     if (MIMEField *field = headers->field_find(h.name, h.name_len); field != nullptr) {
647       headers->field_delete(field);
648     }
649   }
650 
651   return PARSE_RESULT_DONE;
652 }
653 
654 Http2ErrorCode
http2_encode_header_blocks(HTTPHdr * in,uint8_t * out,uint32_t out_len,uint32_t * len_written,HpackHandle & handle,int32_t maximum_table_size)655 http2_encode_header_blocks(HTTPHdr *in, uint8_t *out, uint32_t out_len, uint32_t *len_written, HpackHandle &handle,
656                            int32_t maximum_table_size)
657 {
658   // Limit the maximum table size to the configured value or 64kB at maximum, which is the size advertised by major clients
659   maximum_table_size =
660     std::min(maximum_table_size, static_cast<int32_t>(std::min(Http2::header_table_size_limit, HTTP2_MAX_TABLE_SIZE_LIMIT)));
661   // Set maximum table size only if it is different from current maximum size
662   if (maximum_table_size == hpack_get_maximum_table_size(handle)) {
663     maximum_table_size = -1;
664   }
665 
666   // TODO: It would be better to split Cookie header value
667   int64_t result = hpack_encode_header_block(handle, out, out_len, in, maximum_table_size);
668   if (result < 0) {
669     return Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR;
670   }
671   if (len_written) {
672     *len_written = result;
673   }
674   return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
675 }
676 
677 /*
678  * Decode Header Blocks to Header List.
679  */
680 Http2ErrorCode
http2_decode_header_blocks(HTTPHdr * hdr,const uint8_t * buf_start,const uint32_t buf_len,uint32_t * len_read,HpackHandle & handle,bool & trailing_header,uint32_t maximum_table_size)681 http2_decode_header_blocks(HTTPHdr *hdr, const uint8_t *buf_start, const uint32_t buf_len, uint32_t *len_read, HpackHandle &handle,
682                            bool &trailing_header, uint32_t maximum_table_size)
683 {
684   const MIMEField *field;
685   const char *value;
686   int len;
687   bool is_trailing_header = trailing_header;
688   int64_t result = hpack_decode_header_block(handle, hdr, buf_start, buf_len, Http2::max_header_list_size, maximum_table_size);
689 
690   if (result < 0) {
691     if (result == HPACK_ERROR_COMPRESSION_ERROR) {
692       return Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR;
693     } else if (result == HPACK_ERROR_SIZE_EXCEEDED_ERROR) {
694       return Http2ErrorCode::HTTP2_ERROR_ENHANCE_YOUR_CALM;
695     }
696 
697     return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
698   }
699   if (len_read) {
700     *len_read = result;
701   }
702 
703   MIMEFieldIter iter;
704   unsigned int expected_pseudo_header_count = 4;
705   unsigned int pseudo_header_count          = 0;
706 
707   if (is_trailing_header) {
708     expected_pseudo_header_count = 0;
709   }
710   for (field = hdr->iter_get_first(&iter); field != nullptr; field = hdr->iter_get_next(&iter)) {
711     value = field->name_get(&len);
712     // Pseudo headers must appear before regular headers
713     if (len && value[0] == ':') {
714       ++pseudo_header_count;
715       if (pseudo_header_count > expected_pseudo_header_count) {
716         return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
717       }
718     } else if (len <= 0) {
719       return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
720     } else {
721       if (pseudo_header_count != expected_pseudo_header_count) {
722         return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
723       }
724     }
725   }
726 
727   // rfc7540,sec8.1.2.2: Any message containing connection-specific header
728   // fields MUST be treated as malformed
729   if (hdr->field_find(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION) != nullptr ||
730       hdr->field_find(MIME_FIELD_KEEP_ALIVE, MIME_LEN_KEEP_ALIVE) != nullptr ||
731       hdr->field_find(MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION) != nullptr ||
732       hdr->field_find(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING) != nullptr ||
733       hdr->field_find(MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE) != nullptr) {
734     return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
735   }
736 
737   // :path pseudo header MUST NOT empty for http or https URIs
738   field = hdr->field_find(HTTP2_VALUE_PATH, HTTP2_LEN_PATH);
739   if (field) {
740     field->value_get(&len);
741     if (len == 0) {
742       return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
743     }
744   }
745 
746   // turn on that we have a trailer header
747   const char trailer_name[] = "trailer";
748   field                     = hdr->field_find(trailer_name, sizeof(trailer_name) - 1);
749   if (field) {
750     trailing_header = true;
751   }
752 
753   // when The TE header field is received, it MUST NOT contain any
754   // value other than "trailers".
755   field = hdr->field_find(MIME_FIELD_TE, MIME_LEN_TE);
756   if (field) {
757     value = field->value_get(&len);
758     if (!(len == 8 && memcmp(value, "trailers", 8) == 0)) {
759       return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
760     }
761   }
762 
763   if (!is_trailing_header) {
764     // Check pseudo headers
765     if (hdr->fields_count() >= 4) {
766       if (hdr->field_find(HTTP2_VALUE_SCHEME, HTTP2_LEN_SCHEME) == nullptr ||
767           hdr->field_find(HTTP2_VALUE_METHOD, HTTP2_LEN_METHOD) == nullptr ||
768           hdr->field_find(HTTP2_VALUE_PATH, HTTP2_LEN_PATH) == nullptr ||
769           hdr->field_find(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY) == nullptr ||
770           hdr->field_find(HTTP2_VALUE_STATUS, HTTP2_LEN_STATUS) != nullptr) {
771         // Decoded header field is invalid
772         return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
773       }
774     } else {
775       // Pseudo headers is insufficient
776       return Http2ErrorCode::HTTP2_ERROR_PROTOCOL_ERROR;
777     }
778   }
779 
780   return Http2ErrorCode::HTTP2_ERROR_NO_ERROR;
781 }
782 
783 // Initialize this subsystem with librecords configs (for now)
784 uint32_t Http2::max_concurrent_streams_in      = 100;
785 uint32_t Http2::min_concurrent_streams_in      = 10;
786 uint32_t Http2::max_active_streams_in          = 0;
787 bool Http2::throttling                         = false;
788 uint32_t Http2::stream_priority_enabled        = 0;
789 uint32_t Http2::initial_window_size            = 65535;
790 uint32_t Http2::max_frame_size                 = 16384;
791 uint32_t Http2::header_table_size              = 4096;
792 uint32_t Http2::max_header_list_size           = 4294967295;
793 uint32_t Http2::accept_no_activity_timeout     = 120;
794 uint32_t Http2::no_activity_timeout_in         = 120;
795 uint32_t Http2::active_timeout_in              = 0;
796 uint32_t Http2::push_diary_size                = 256;
797 uint32_t Http2::zombie_timeout_in              = 0;
798 float Http2::stream_error_rate_threshold       = 0.1;
799 uint32_t Http2::max_settings_per_frame         = 7;
800 uint32_t Http2::max_settings_per_minute        = 14;
801 uint32_t Http2::max_settings_frames_per_minute = 14;
802 uint32_t Http2::max_ping_frames_per_minute     = 60;
803 uint32_t Http2::max_priority_frames_per_minute = 120;
804 float Http2::min_avg_window_update             = 2560.0;
805 uint32_t Http2::con_slow_log_threshold         = 0;
806 uint32_t Http2::stream_slow_log_threshold      = 0;
807 uint32_t Http2::header_table_size_limit        = 65536;
808 uint32_t Http2::write_buffer_block_size        = 262144;
809 float Http2::write_size_threshold              = 0.5;
810 uint32_t Http2::write_time_threshold           = 100;
811 
812 void
init()813 Http2::init()
814 {
815   REC_EstablishStaticConfigInt32U(max_concurrent_streams_in, "proxy.config.http2.max_concurrent_streams_in");
816   REC_EstablishStaticConfigInt32U(min_concurrent_streams_in, "proxy.config.http2.min_concurrent_streams_in");
817   REC_EstablishStaticConfigInt32U(max_active_streams_in, "proxy.config.http2.max_active_streams_in");
818   REC_EstablishStaticConfigInt32U(stream_priority_enabled, "proxy.config.http2.stream_priority_enabled");
819   REC_EstablishStaticConfigInt32U(initial_window_size, "proxy.config.http2.initial_window_size_in");
820   REC_EstablishStaticConfigInt32U(max_frame_size, "proxy.config.http2.max_frame_size");
821   REC_EstablishStaticConfigInt32U(header_table_size, "proxy.config.http2.header_table_size");
822   REC_EstablishStaticConfigInt32U(max_header_list_size, "proxy.config.http2.max_header_list_size");
823   REC_EstablishStaticConfigInt32U(accept_no_activity_timeout, "proxy.config.http2.accept_no_activity_timeout");
824   REC_EstablishStaticConfigInt32U(no_activity_timeout_in, "proxy.config.http2.no_activity_timeout_in");
825   REC_EstablishStaticConfigInt32U(active_timeout_in, "proxy.config.http2.active_timeout_in");
826   REC_EstablishStaticConfigInt32U(push_diary_size, "proxy.config.http2.push_diary_size");
827   REC_EstablishStaticConfigInt32U(zombie_timeout_in, "proxy.config.http2.zombie_debug_timeout_in");
828   REC_EstablishStaticConfigFloat(stream_error_rate_threshold, "proxy.config.http2.stream_error_rate_threshold");
829   REC_EstablishStaticConfigInt32U(max_settings_per_frame, "proxy.config.http2.max_settings_per_frame");
830   REC_EstablishStaticConfigInt32U(max_settings_per_minute, "proxy.config.http2.max_settings_per_minute");
831   REC_EstablishStaticConfigInt32U(max_settings_frames_per_minute, "proxy.config.http2.max_settings_frames_per_minute");
832   REC_EstablishStaticConfigInt32U(max_ping_frames_per_minute, "proxy.config.http2.max_ping_frames_per_minute");
833   REC_EstablishStaticConfigInt32U(max_priority_frames_per_minute, "proxy.config.http2.max_priority_frames_per_minute");
834   REC_EstablishStaticConfigFloat(min_avg_window_update, "proxy.config.http2.min_avg_window_update");
835   REC_EstablishStaticConfigInt32U(con_slow_log_threshold, "proxy.config.http2.connection.slow.log.threshold");
836   REC_EstablishStaticConfigInt32U(stream_slow_log_threshold, "proxy.config.http2.stream.slow.log.threshold");
837   REC_EstablishStaticConfigInt32U(header_table_size_limit, "proxy.config.http2.header_table_size_limit");
838   REC_EstablishStaticConfigInt32U(write_buffer_block_size, "proxy.config.http2.write_buffer_block_size");
839   REC_EstablishStaticConfigFloat(write_size_threshold, "proxy.config.http2.write_size_threshold");
840   REC_EstablishStaticConfigInt32U(write_time_threshold, "proxy.config.http2.write_time_threshold");
841 
842   // If any settings is broken, ATS should not start
843   ink_release_assert(http2_settings_parameter_is_valid({HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, max_concurrent_streams_in}));
844   ink_release_assert(http2_settings_parameter_is_valid({HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, min_concurrent_streams_in}));
845   ink_release_assert(http2_settings_parameter_is_valid({HTTP2_SETTINGS_INITIAL_WINDOW_SIZE, initial_window_size}));
846   ink_release_assert(http2_settings_parameter_is_valid({HTTP2_SETTINGS_MAX_FRAME_SIZE, max_frame_size}));
847   ink_release_assert(http2_settings_parameter_is_valid({HTTP2_SETTINGS_HEADER_TABLE_SIZE, header_table_size}));
848   ink_release_assert(http2_settings_parameter_is_valid({HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE, max_header_list_size}));
849 
850 #define HTTP2_CLEAR_DYN_STAT(x)          \
851   do {                                   \
852     RecSetRawStatSum(http2_rsb, x, 0);   \
853     RecSetRawStatCount(http2_rsb, x, 0); \
854   } while (0);
855 
856   // Setup statistics
857   http2_rsb = RecAllocateRawStatBlock(static_cast<int>(HTTP2_N_STATS));
858   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_CURRENT_CLIENT_CONNECTION_NAME, RECD_INT, RECP_NON_PERSISTENT,
859                      static_cast<int>(HTTP2_STAT_CURRENT_CLIENT_SESSION_COUNT), RecRawStatSyncSum);
860   HTTP2_CLEAR_DYN_STAT(HTTP2_STAT_CURRENT_CLIENT_SESSION_COUNT);
861   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_CURRENT_ACTIVE_CLIENT_CONNECTION_NAME, RECD_INT, RECP_NON_PERSISTENT,
862                      static_cast<int>(HTTP2_STAT_CURRENT_ACTIVE_CLIENT_CONNECTION_COUNT), RecRawStatSyncSum);
863   HTTP2_CLEAR_DYN_STAT(HTTP2_STAT_CURRENT_ACTIVE_CLIENT_CONNECTION_COUNT);
864   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_CURRENT_CLIENT_STREAM_NAME, RECD_INT, RECP_NON_PERSISTENT,
865                      static_cast<int>(HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT), RecRawStatSyncSum);
866   HTTP2_CLEAR_DYN_STAT(HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT);
867   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_TOTAL_CLIENT_STREAM_NAME, RECD_INT, RECP_PERSISTENT,
868                      static_cast<int>(HTTP2_STAT_TOTAL_CLIENT_STREAM_COUNT), RecRawStatSyncCount);
869   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_TOTAL_TRANSACTIONS_TIME_NAME, RECD_INT, RECP_PERSISTENT,
870                      static_cast<int>(HTTP2_STAT_TOTAL_TRANSACTIONS_TIME), RecRawStatSyncSum);
871   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_TOTAL_CLIENT_CONNECTION_NAME, RECD_INT, RECP_PERSISTENT,
872                      static_cast<int>(HTTP2_STAT_TOTAL_CLIENT_CONNECTION_COUNT), RecRawStatSyncSum);
873   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_CONNECTION_ERRORS_NAME, RECD_INT, RECP_PERSISTENT,
874                      static_cast<int>(HTTP2_STAT_CONNECTION_ERRORS_COUNT), RecRawStatSyncSum);
875   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_STREAM_ERRORS_NAME, RECD_INT, RECP_PERSISTENT,
876                      static_cast<int>(HTTP2_STAT_STREAM_ERRORS_COUNT), RecRawStatSyncSum);
877   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_DEFAULT_NAME, RECD_INT, RECP_PERSISTENT,
878                      static_cast<int>(HTTP2_STAT_SESSION_DIE_DEFAULT), RecRawStatSyncSum);
879   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_OTHER_NAME, RECD_INT, RECP_PERSISTENT,
880                      static_cast<int>(HTTP2_STAT_SESSION_DIE_OTHER), RecRawStatSyncSum);
881   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_EOS_NAME, RECD_INT, RECP_PERSISTENT,
882                      static_cast<int>(HTTP2_STAT_SESSION_DIE_EOS), RecRawStatSyncSum);
883   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_ACTIVE_NAME, RECD_INT, RECP_PERSISTENT,
884                      static_cast<int>(HTTP2_STAT_SESSION_DIE_ACTIVE), RecRawStatSyncSum);
885   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_INACTIVE_NAME, RECD_INT, RECP_PERSISTENT,
886                      static_cast<int>(HTTP2_STAT_SESSION_DIE_INACTIVE), RecRawStatSyncSum);
887   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_ERROR_NAME, RECD_INT, RECP_PERSISTENT,
888                      static_cast<int>(HTTP2_STAT_SESSION_DIE_ERROR), RecRawStatSyncSum);
889   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE_NAME, RECD_INT, RECP_PERSISTENT,
890                      static_cast<int>(HTTP2_STAT_SESSION_DIE_HIGH_ERROR_RATE), RecRawStatSyncSum);
891   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
892                      static_cast<int>(HTTP2_STAT_MAX_SETTINGS_PER_FRAME_EXCEEDED), RecRawStatSyncSum);
893   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
894                      static_cast<int>(HTTP2_STAT_MAX_SETTINGS_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
895   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
896                      static_cast<int>(HTTP2_STAT_MAX_SETTINGS_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
897   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
898                      static_cast<int>(HTTP2_STAT_MAX_PING_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
899   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED_NAME, RECD_INT, RECP_PERSISTENT,
900                      static_cast<int>(HTTP2_STAT_MAX_PRIORITY_FRAMES_PER_MINUTE_EXCEEDED), RecRawStatSyncSum);
901   RecRegisterRawStat(http2_rsb, RECT_PROCESS, HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE_NAME, RECD_INT, RECP_PERSISTENT,
902                      static_cast<int>(HTTP2_STAT_INSUFFICIENT_AVG_WINDOW_UPDATE), RecRawStatSyncSum);
903 
904   http2_init();
905 }
906 
907 /**
908   mime_init() needs to be called
909  */
910 void
http2_init()911 http2_init()
912 {
913   ink_assert(MIME_FIELD_CONNECTION != nullptr);
914   ink_assert(MIME_FIELD_KEEP_ALIVE != nullptr);
915   ink_assert(MIME_FIELD_PROXY_CONNECTION != nullptr);
916   ink_assert(MIME_FIELD_TRANSFER_ENCODING != nullptr);
917   ink_assert(MIME_FIELD_UPGRADE != nullptr);
918 
919   http2_connection_specific_headers[0] = {MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION};
920   http2_connection_specific_headers[1] = {MIME_FIELD_KEEP_ALIVE, MIME_LEN_KEEP_ALIVE};
921   http2_connection_specific_headers[2] = {MIME_FIELD_PROXY_CONNECTION, MIME_LEN_PROXY_CONNECTION};
922   http2_connection_specific_headers[3] = {MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING};
923   http2_connection_specific_headers[4] = {MIME_FIELD_UPGRADE, MIME_LEN_UPGRADE};
924 }
925