Coverage Report

Created: 2026-10-23 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/hdrs/HTTP.h
Line
Count
Source
1
/** @file
2
3
  A brief file description
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
 */
23
24
#pragma once
25
26
#include <cassert>
27
#include <string_view>
28
29
using namespace std::literals;
30
31
#include "tscore/Arena.h"
32
#include "tscore/CryptoHash.h"
33
#include "tscore/HTTPVersion.h"
34
#include "proxy/hdrs/MIME.h"
35
#include "proxy/hdrs/URL.h"
36
37
#include "tscore/ink_apidefs.h"
38
39
class Http2HeaderTable;
40
41
enum class HTTPStatus {
42
  NONE = 0,
43
44
  CONTINUE           = 100,
45
  SWITCHING_PROTOCOL = 101,
46
  PROCESSING         = 102,
47
  EARLY_HINTS        = 103,
48
49
  OK                            = 200,
50
  CREATED                       = 201,
51
  ACCEPTED                      = 202,
52
  NON_AUTHORITATIVE_INFORMATION = 203,
53
  NO_CONTENT                    = 204,
54
  RESET_CONTENT                 = 205,
55
  PARTIAL_CONTENT               = 206,
56
57
  MULTIPLE_CHOICES   = 300,
58
  MOVED_PERMANENTLY  = 301,
59
  MOVED_TEMPORARILY  = 302,
60
  SEE_OTHER          = 303,
61
  NOT_MODIFIED       = 304,
62
  USE_PROXY          = 305,
63
  TEMPORARY_REDIRECT = 307,
64
  PERMANENT_REDIRECT = 308,
65
66
  BAD_REQUEST                   = 400,
67
  UNAUTHORIZED                  = 401,
68
  PAYMENT_REQUIRED              = 402,
69
  FORBIDDEN                     = 403,
70
  NOT_FOUND                     = 404,
71
  METHOD_NOT_ALLOWED            = 405,
72
  NOT_ACCEPTABLE                = 406,
73
  PROXY_AUTHENTICATION_REQUIRED = 407,
74
  REQUEST_TIMEOUT               = 408,
75
  CONFLICT                      = 409,
76
  GONE                          = 410,
77
  LENGTH_REQUIRED               = 411,
78
  PRECONDITION_FAILED           = 412,
79
  REQUEST_ENTITY_TOO_LARGE      = 413,
80
  REQUEST_URI_TOO_LONG          = 414,
81
  UNSUPPORTED_MEDIA_TYPE        = 415,
82
  RANGE_NOT_SATISFIABLE         = 416,
83
  TOO_EARLY                     = 425,
84
85
  INTERNAL_SERVER_ERROR = 500,
86
  NOT_IMPLEMENTED       = 501,
87
  BAD_GATEWAY           = 502,
88
  SERVICE_UNAVAILABLE   = 503,
89
  GATEWAY_TIMEOUT       = 504,
90
  HTTPVER_NOT_SUPPORTED = 505
91
};
92
93
enum class HTTPKeepAlive {
94
  UNDEFINED = 0,
95
  NO_KEEPALIVE,
96
  KEEPALIVE,
97
};
98
99
enum class HTTPWarningCode {
100
  NONE = 0,
101
102
  RESPONSE_STALE         = 110,
103
  REVALIDATION_FAILED    = 111,
104
  DISCONNECTED_OPERATION = 112,
105
  HERUISTIC_EXPIRATION   = 113,
106
  TRANSFORMATION_APPLIED = 114,
107
  MISC_WARNING           = 199
108
};
109
110
/* squid log codes
111
   There is code (e.g. logstats) that depends on these errors coming at the end of this enum */
112
enum class SquidLogCode {
113
  EMPTY                     = '0',
114
  TCP_HIT                   = '1',
115
  TCP_DISK_HIT              = '2',
116
  TCP_MEM_HIT               = '.', // Don't want to change others codes
117
  TCP_MISS                  = '3',
118
  TCP_EXPIRED_MISS          = '4',
119
  TCP_REFRESH_HIT           = '5',
120
  TCP_REF_FAIL_HIT          = '6',
121
  TCP_REFRESH_MISS          = '7',
122
  TCP_CLIENT_REFRESH        = '8',
123
  TCP_IMS_HIT               = '9',
124
  TCP_IMS_MISS              = 'a',
125
  TCP_SWAPFAIL              = 'b',
126
  TCP_DENIED                = 'c',
127
  TCP_WEBFETCH_MISS         = 'd',
128
  TCP_FUTURE_2              = 'f',
129
  TCP_HIT_REDIRECT          = '[', // standard redirect
130
  TCP_MISS_REDIRECT         = ']', // standard redirect
131
  TCP_HIT_X_REDIRECT        = '<', // extended redirect
132
  TCP_MISS_X_REDIRECT       = '>', // extended redirect
133
  UDP_HIT                   = 'g',
134
  UDP_WEAK_HIT              = 'h',
135
  UDP_HIT_OBJ               = 'i',
136
  UDP_MISS                  = 'j',
137
  UDP_DENIED                = 'k',
138
  UDP_INVALID               = 'l',
139
  UDP_RELOADING             = 'm',
140
  UDP_FUTURE_1              = 'n',
141
  UDP_FUTURE_2              = 'o',
142
  ERR_READ_TIMEOUT          = 'p',
143
  ERR_LIFETIME_EXP          = 'q',
144
  ERR_POST_ENTITY_TOO_LARGE = 'L',
145
  ERR_NO_CLIENTS_BIG_OBJ    = 'r',
146
  ERR_READ_ERROR            = 's',
147
  ERR_CLIENT_ABORT          = 't', // Client side abort logging
148
  ERR_CONNECT_FAIL          = 'u',
149
  ERR_INVALID_REQ           = 'v',
150
  ERR_UNSUP_REQ             = 'w',
151
  ERR_INVALID_URL           = 'x',
152
  ERR_NO_FDS                = 'y',
153
  ERR_DNS_FAIL              = 'z',
154
  ERR_NOT_IMPLEMENTED       = 'A',
155
  ERR_CANNOT_FETCH          = 'B',
156
  ERR_NO_RELAY              = 'C',
157
  ERR_DISK_IO               = 'D',
158
  ERR_ZERO_SIZE_OBJECT      = 'E',
159
  TCP_CF_HIT                = 'F', // Collapsed forwarding HIT also known as Read while write hit
160
  ERR_PROXY_DENIED          = 'G',
161
  ERR_WEBFETCH_DETECTED     = 'H',
162
  ERR_FUTURE_1              = 'I',
163
  ERR_CLIENT_READ_ERROR     = 'J', // Client side abort logging
164
  ERR_LOOP_DETECTED         = 'K', // Loop or cycle detected, request came back to this server
165
  ERR_TUN_ACTIVE_TIMEOUT    = 'T', // Tunnel (CONNECT) active timeout
166
  ERR_UNKNOWN               = 'Z'
167
};
168
169
// squid log subcodes
170
enum class SquidSubcode {
171
  EMPTY                     = '0',
172
  NUM_REDIRECTIONS_EXCEEDED = '1',
173
};
174
175
/* squid hierarchy codes */
176
enum class SquidHierarchyCode {
177
  EMPTY                           = '0',
178
  NONE                            = '1',
179
  DIRECT                          = '2',
180
  SIBLING_HIT                     = '3',
181
  PARENT_HIT                      = '4',
182
  DEFAULT_PARENT                  = '5',
183
  SINGLE_PARENT                   = '6',
184
  FIRST_UP_PARENT                 = '7',
185
  NO_PARENT_DIRECT                = '8',
186
  FIRST_PARENT_MISS               = '9',
187
  LOCAL_IP_DIRECT                 = 'a',
188
  FIREWALL_IP_DIRECT              = 'b',
189
  NO_DIRECT_FAIL                  = 'c',
190
  SOURCE_FASTEST                  = 'd',
191
  SIBLING_UDP_HIT_OBJ             = 'e',
192
  PARENT_UDP_HIT_OBJ              = 'f',
193
  PASSTHROUGH_PARENT              = 'g',
194
  SSL_PARENT_MISS                 = 'h',
195
  INVALID_CODE                    = 'i',
196
  TIMEOUT_DIRECT                  = 'j',
197
  TIMEOUT_SIBLING_HIT             = 'k',
198
  TIMEOUT_PARENT_HIT              = 'l',
199
  TIMEOUT_DEFAULT_PARENT          = 'm',
200
  TIMEOUT_SINGLE_PARENT           = 'n',
201
  TIMEOUT_FIRST_UP_PARENT         = 'o',
202
  TIMEOUT_NO_PARENT_DIRECT        = 'p',
203
  TIMEOUT_FIRST_PARENT_MISS       = 'q',
204
  TIMEOUT_LOCAL_IP_DIRECT         = 'r',
205
  TIMEOUT_FIREWALL_IP_DIRECT      = 's',
206
  TIMEOUT_NO_DIRECT_FAIL          = 't',
207
  TIMEOUT_SOURCE_FASTEST          = 'u',
208
  TIMEOUT_SIBLING_UDP_HIT_OBJ     = 'v',
209
  TIMEOUT_PARENT_UDP_HIT_OBJ      = 'w',
210
  TIMEOUT_PASSTHROUGH_PARENT      = 'x',
211
  TIMEOUT_TIMEOUT_SSL_PARENT_MISS = 'y',
212
  INVALID_ASSIGNED_CODE           = 'z'
213
};
214
215
/* squid hit/miss codes */
216
enum SquidHitMissCode {
217
  SQUID_HIT_RESERVED                   = '0', // Kinda wonky that this is '0', so skipping 'A' for now
218
  SQUID_HIT_LEVEL_1                    = 'B',
219
  SQUID_HIT_LEVEL_2                    = 'C',
220
  SQUID_HIT_LEVEL_3                    = 'D',
221
  SQUID_HIT_LEVEL_4                    = 'E',
222
  SQUID_HIT_LEVEL_5                    = 'F',
223
  SQUID_HIT_LEVEL_6                    = 'G',
224
  SQUID_HIT_LEVEL_7                    = 'H',
225
  SQUID_HIT_LEVEL_8                    = 'I',
226
  SQUID_HIT_LEVEl_9                    = 'J',
227
  SQUID_MISS_NONE                      = '1',
228
  SQUID_MISS_HTTP_NON_CACHE            = '3',
229
  SQUID_MISS_HTTP_NO_DLE               = '5',
230
  SQUID_MISS_HTTP_NO_LE                = '6',
231
  SQUID_MISS_HTTP_CONTENT              = '7',
232
  SQUID_MISS_PRAGMA_NOCACHE            = '8',
233
  SQUID_MISS_PASS                      = '9',
234
  SQUID_MISS_PRE_EXPIRED               = 'a',
235
  SQUID_MISS_ERROR                     = 'b',
236
  SQUID_MISS_CACHE_BYPASS              = 'c',
237
  SQUID_HIT_MISS_INVALID_ASSIGNED_CODE = 'z',
238
  // These are pre-allocated with special semantics, added here for convenience
239
  SQUID_HIT_RAM     = SQUID_HIT_LEVEL_1,
240
  SQUID_HIT_SSD     = SQUID_HIT_LEVEL_2,
241
  SQUID_HIT_DISK    = SQUID_HIT_LEVEL_3,
242
  SQUID_HIT_CLUSTER = SQUID_HIT_LEVEL_4,
243
  SQUID_HIT_NET     = SQUID_HIT_LEVEL_5,
244
  SQUID_HIT_RWW     = SQUID_HIT_LEVEL_6
245
};
246
247
constexpr std::string_view PSEUDO_HEADER_SCHEME    = ":scheme";
248
constexpr std::string_view PSEUDO_HEADER_AUTHORITY = ":authority";
249
constexpr std::string_view PSEUDO_HEADER_PATH      = ":path";
250
constexpr std::string_view PSEUDO_HEADER_METHOD    = ":method";
251
constexpr std::string_view PSEUDO_HEADER_STATUS    = ":status";
252
253
enum class HTTPType {
254
  UNKNOWN,
255
  REQUEST,
256
  RESPONSE,
257
};
258
259
struct HTTPHdrImpl : public HdrHeapObjImpl {
260
  // HdrHeapObjImpl is 4 bytes
261
  HTTPType    m_polarity; // request or response or unknown
262
  HTTPVersion m_version;  // cooked version number
263
  // 12 bytes means 4 bytes padding here on 64-bit architectures
264
  union {
265
    struct {
266
      URLImpl    *m_url_impl;
267
      const char *m_ptr_method;
268
      uint16_t    m_len_method;
269
      int16_t     m_method_wks_idx;
270
    } req;
271
272
    struct {
273
      const char *m_ptr_reason;
274
      uint16_t    m_len_reason;
275
      int16_t     m_status;
276
    } resp;
277
  } u;
278
279
  MIMEHdrImpl *m_fields_impl;
280
281
  // Marshaling Functions
282
  int    marshal(MarshalXlate *ptr_xlate, int num_ptr, MarshalXlate *str_xlate, int num_str);
283
  void   unmarshal(intptr_t offset);
284
  void   move_strings(HdrStrHeap *new_heap);
285
  size_t strings_length();
286
287
  /** Rebuild everything in this header that indexes the well-known string table.
288
   *
289
   * That is the request method index, the request URL's scheme index, and the field indexes,
290
   * presence bits and slot accelerators of the MIME header. All of them are caches over strings
291
   * that are stored in the header itself, so they can always be rebuilt, and they must be after
292
   * the header is read back from a cached object: the object may have been written by a build
293
   * whose well-known string table differed from this one's, in which case the stored indexes
294
   * denote different strings here than they did there.
295
   *
296
   * Call this only once the header is fully unmarshalled. It walks the MIME field blocks, which
297
   * are separate heap objects and are not usable until their own pointers have been swizzled.
298
   */
299
  void recompute_wks_indices();
300
301
  // Sanity Check Functions
302
  void check_strings(HeapCheck *heaps, int num_heaps);
303
};
304
305
struct HTTPValAccept {
306
  char  *type;
307
  char  *subtype;
308
  double qvalue;
309
};
310
311
struct HTTPValAcceptCharset {
312
  char  *charset;
313
  double qvalue;
314
};
315
316
struct HTTPValAcceptEncoding {
317
  char  *encoding;
318
  double qvalue;
319
};
320
321
struct HTTPValAcceptLanguage {
322
  char  *language;
323
  double qvalue;
324
};
325
326
struct HTTPValFieldList {
327
  char             *name;
328
  HTTPValFieldList *next;
329
};
330
331
struct HTTPValCacheControl {
332
  const char *directive;
333
334
  union {
335
    int               delta_seconds;
336
    HTTPValFieldList *field_names;
337
  } u;
338
};
339
340
struct HTTPValRange {
341
  int           start;
342
  int           end;
343
  HTTPValRange *next;
344
};
345
346
struct HTTPValTE {
347
  char  *encoding;
348
  double qvalue;
349
};
350
351
struct HTTPParser {
352
  bool       m_parsing_http = false;
353
  MIMEParser m_mime_parser;
354
};
355
356
extern c_str_view HTTP_METHOD_CONNECT;
357
extern c_str_view HTTP_METHOD_DELETE;
358
extern c_str_view HTTP_METHOD_GET;
359
extern c_str_view HTTP_METHOD_HEAD;
360
extern c_str_view HTTP_METHOD_OPTIONS;
361
extern c_str_view HTTP_METHOD_POST;
362
extern c_str_view HTTP_METHOD_PURGE;
363
extern c_str_view HTTP_METHOD_PUT;
364
extern c_str_view HTTP_METHOD_TRACE;
365
extern c_str_view HTTP_METHOD_PUSH;
366
367
extern int HTTP_WKSIDX_CONNECT;
368
extern int HTTP_WKSIDX_DELETE;
369
extern int HTTP_WKSIDX_GET;
370
extern int HTTP_WKSIDX_HEAD;
371
extern int HTTP_WKSIDX_OPTIONS;
372
extern int HTTP_WKSIDX_POST;
373
extern int HTTP_WKSIDX_PURGE;
374
extern int HTTP_WKSIDX_PUT;
375
extern int HTTP_WKSIDX_TRACE;
376
extern int HTTP_WKSIDX_PUSH;
377
extern int HTTP_WKSIDX_METHODS_CNT;
378
379
extern c_str_view HTTP_VALUE_BYTES;
380
extern c_str_view HTTP_VALUE_CHUNKED;
381
extern c_str_view HTTP_VALUE_CLOSE;
382
extern c_str_view HTTP_VALUE_COMPRESS;
383
extern c_str_view HTTP_VALUE_DEFLATE;
384
extern c_str_view HTTP_VALUE_GZIP;
385
extern c_str_view HTTP_VALUE_BROTLI;
386
extern c_str_view HTTP_VALUE_ZSTD;
387
extern c_str_view HTTP_VALUE_IDENTITY;
388
extern c_str_view HTTP_VALUE_KEEP_ALIVE;
389
extern c_str_view HTTP_VALUE_MAX_AGE;
390
extern c_str_view HTTP_VALUE_MAX_STALE;
391
extern c_str_view HTTP_VALUE_MIN_FRESH;
392
extern c_str_view HTTP_VALUE_MUST_REVALIDATE;
393
extern c_str_view HTTP_VALUE_NONE;
394
extern c_str_view HTTP_VALUE_NO_CACHE;
395
extern c_str_view HTTP_VALUE_NO_STORE;
396
extern c_str_view HTTP_VALUE_NO_TRANSFORM;
397
extern c_str_view HTTP_VALUE_ONLY_IF_CACHED;
398
extern c_str_view HTTP_VALUE_PRIVATE;
399
extern c_str_view HTTP_VALUE_PROXY_REVALIDATE;
400
extern c_str_view HTTP_VALUE_PUBLIC;
401
extern c_str_view HTTP_VALUE_S_MAXAGE;
402
extern c_str_view HTTP_VALUE_NEED_REVALIDATE_ONCE;
403
extern c_str_view HTTP_VALUE_100_CONTINUE;
404
405
/* Private */
406
void http_hdr_adjust(HTTPHdrImpl *hdrp, int32_t offset, int32_t length, int32_t delta);
407
408
/* Public */
409
void http_init();
410
411
HTTPHdrImpl *http_hdr_create(HdrHeap *heap, HTTPType polarity, HTTPVersion version);
412
void         http_hdr_init(HdrHeap *heap, HTTPHdrImpl *hh, HTTPType polarity, HTTPVersion version);
413
HTTPHdrImpl *http_hdr_clone(HTTPHdrImpl *s_hh, HdrHeap *s_heap, HdrHeap *d_heap);
414
void         http_hdr_copy_onto(HTTPHdrImpl *s_hh, HdrHeap *s_heap, HTTPHdrImpl *d_hh, HdrHeap *d_heap, bool inherit_strs);
415
416
int http_hdr_print(HTTPHdrImpl const *hh, char *buf, int bufsize, int *bufindex, int *dumpoffset);
417
418
void http_hdr_describe(HdrHeapObjImpl *obj, bool recurse = true);
419
420
bool http_hdr_version_set(HTTPHdrImpl *hh, const HTTPVersion &ver);
421
422
std::string_view http_hdr_method_get(HTTPHdrImpl *hh);
423
void http_hdr_method_set(HdrHeap *heap, HTTPHdrImpl *hh, std::string_view method, int16_t method_wks_idx, bool must_copy);
424
425
void http_hdr_url_set(HdrHeap *heap, HTTPHdrImpl *hh, URLImpl *url);
426
427
// HTTPStatus             http_hdr_status_get (HTTPHdrImpl *hh);
428
void             http_hdr_status_set(HTTPHdrImpl *hh, HTTPStatus status);
429
std::string_view http_hdr_reason_get(HTTPHdrImpl *hh);
430
void             http_hdr_reason_set(HdrHeap *heap, HTTPHdrImpl *hh, std::string_view value, bool must_copy);
431
const char      *http_hdr_reason_lookup(HTTPStatus status);
432
433
void        http_parser_init(HTTPParser *parser);
434
void        http_parser_clear(HTTPParser *parser);
435
ParseResult http_parser_parse_req(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
436
                                  bool must_copy_strings, bool eof, int strict_uri_parsing, size_t max_request_line_size,
437
                                  size_t max_hdr_field_size);
438
ParseResult validate_hdr_request_target(int method_wks_idx, URLImpl *url);
439
440
// This calls http_parse_host_header internally to parse the Host field value
441
// when present, so it enforces the same syntax rules and also validates the
442
// port number when specified.
443
ParseResult validate_hdr_host(HTTPHdrImpl *hh);
444
445
// This parses and validates the Host field value.
446
bool http_parse_host_header(std::string_view value, std::string_view &host, int &port, bool &has_port);
447
448
ParseResult validate_hdr_content_length(HdrHeap *heap, HTTPHdrImpl *hh);
449
ParseResult http_parser_parse_resp(HTTPParser *parser, HdrHeap *heap, HTTPHdrImpl *hh, const char **start, const char *end,
450
                                   bool must_copy_strings, bool eof);
451
452
HTTPStatus  http_parse_status(const char *start, const char *end);
453
HTTPVersion http_parse_version(const char *start, const char *end);
454
455
/*
456
HTTPValAccept*         http_parse_accept (const char *buf, Arena *arena);
457
HTTPValAcceptCharset*  http_parse_accept_charset (const char *buf, Arena *arena);
458
HTTPValAcceptEncoding* http_parse_accept_encoding (const char *buf, Arena *arena);
459
HTTPValAcceptLanguage* http_parse_accept_language (const char *buf, Arena *arena);
460
HTTPValCacheControl*   http_parse_cache_control (const char *buf, Arena *arena);
461
const char*            http_parse_cache_directive (const char **buf);
462
HTTPValRange*          http_parse_range (const char *buf, Arena *arena);
463
*/
464
HTTPValTE *http_parse_te(const char *buf, int len, Arena *arena);
465
466
bool is_http1_hdr_version_supported(const HTTPVersion &http_version);
467
468
class IOBufferReader;
469
470
/** HTTP Header class.
471
 *
472
 * @warning Changing the size of this class (adding/removing fields) will change
473
 * the on-disk cache format and cause cache incompatibility. The HTTPCacheAlt
474
 * structure contains embedded HTTPHdr objects, and the cache marshalling code
475
 * uses sizeof(HTTPCacheAlt) to read/write cache entries. Any size change will
476
 * cause "vector inconsistency" errors when reading cache entries written by a
477
 * different version.
478
 */
479
class HTTPHdr : public MIMEHdr
480
{
481
public:
482
  HTTPHdrImpl       *m_http = nullptr;
483
  mutable URL        m_url_cached;
484
  mutable MIMEField *m_host_mime             = nullptr;
485
  mutable int        m_host_length           = 0;     ///< Length of hostname (parsed, excludes port).
486
  mutable int        m_port                  = 0;     ///< Target port.
487
  mutable bool       m_target_cached         = false; ///< Whether host name and port are cached.
488
  mutable bool       m_target_in_url         = false; ///< Whether host name and port are in the URL.
489
  mutable bool       m_100_continue_sent     = false; ///< Whether ATS sent a 100 Continue optimized response.
490
  mutable bool       m_100_continue_required = false; ///< Whether 100_continue is in the Expect header.
491
  /// Set if the port was effectively specified in the header.
492
  /// @c true if the target (in the URL or the HOST field) also specified
493
  /// a port. That is, @c true if whatever source had the target host
494
  /// also had a port, @c false otherwise.
495
  mutable bool m_port_in_header = false;
496
497
  mutable bool early_data = false;
498
499
24.5k
  HTTPHdr() = default; // Force the creation of the default constructor
500
501
  int valid() const;
502
503
  // destroy() and clear() name-hide HdrHeapSDKHandle's non-virtual versions
504
  // Dispatch is static; "override" doesn't apply
505
  void create(HTTPType polarity, HTTPVersion version = HTTP_INVALID, HdrHeap *heap = nullptr);
506
  void destroy();
507
  void clear();
508
  void reset();
509
  void copy(const HTTPHdr *hdr);
510
  void copy_shallow(const HTTPHdr *hdr);
511
512
  int unmarshal(char *buf, int len, RefCountObj *block_ref);
513
514
  int print(char *buf, int bufsize, int *bufindex, int *dumpoffset) const;
515
516
  /** Returns the serialized byte length of the HTTP header.
517
   *
518
   * The count includes the request-line (for requests) or status-line (for
519
   * responses), all header fields, and the terminating blank line. The message
520
   * body is not included.
521
   *
522
   * @note Internal fields whose names begin with @c '@' are counted here even
523
   *       though @c print() omits them from its output, so this length may
524
   *       exceed the number of bytes @c print() actually writes.
525
   *
526
   * @return Serialized byte length of the header.
527
   *
528
   * @pre The header must be initialized.
529
   *
530
   * @par Thread Safety
531
   *   Not thread-safe.
532
   */
533
  int length_get() const;
534
535
  HTTPType type_get() const;
536
537
  HTTPVersion version_get() const;
538
  void        version_set(HTTPVersion version);
539
540
  std::string_view method_get();
541
  int              method_get_wksidx() const;
542
  void             method_set(std::string_view value);
543
544
  URL *url_create(URL *url);
545
546
  URL *url_get() const;
547
  URL *url_get(URL *url);
548
  /** Get a string with the effective URL in it.
549
      If @a length is not @c NULL then the length of the string
550
      is stored in the int pointed to by @a length.
551
552
      Note that this can be different from getting the @c URL
553
      and invoking @c URL::string_get if the host is in a header
554
      field and not explicitly in the URL.
555
   */
556
  char *url_string_get(Arena *arena  = nullptr, ///< Arena to use, or @c malloc if NULL.
557
                       int   *length = nullptr  ///< Store string length here.
558
  );
559
  /** Get a string with the effective URL in it.
560
      This is automatically allocated if needed in the request heap.
561
562
      @see url_string_get
563
   */
564
  char *url_string_get_ref(int *length = nullptr ///< Store string length here.
565
  );
566
567
  /** Print the URL.
568
      Output is not null terminated.
569
      @return 0 on failure, non-zero on success.
570
   */
571
  int url_print(char    *buff,                                    ///< Output buffer
572
                int      length,                                  ///< Length of @a buffer
573
                int     *offset,                                  ///< [in,out] ???
574
                int     *skip,                                    ///< [in,out] ???
575
                unsigned normalization_flags = URLNormalize::NONE ///< host/scheme normalized to lower case
576
  );
577
578
  /** Return the length of the URL that url_print() will create.
579
      @return -1 on failure, non-negative on success.
580
   */
581
  int url_printed_length(unsigned normalizaion_flags = URLNormalize::NONE);
582
583
  /** Get the URL path.
584
      This is a reference, not allocated.
585
      @return A string_view to the path or an empty string_view if there is no valid URL.
586
  */
587
  std::string_view path_get();
588
589
  /** Get the URL query.
590
      This is a reference, not allocated.
591
      @return A string_view to the query or an empty string_view if there is no valid URL.
592
  */
593
  std::string_view query_get();
594
595
  /** Get the URL fragment.
596
      This is a reference, not allocated.
597
      @return A string_view to the fragment or an empty string_view if there is no valid URL.
598
  */
599
  std::string_view fragment_get();
600
601
  /** Get the target host name.
602
      The length is returned in @a length if non-NULL.
603
      @note The results are cached so this is fast after the first call.
604
      @return A string_view to the host name.
605
  */
606
  std::string_view host_get() const;
607
608
  /** Get the target port.
609
      If the target port is not found then it is adjusted to the
610
      default port for the URL type.
611
      @note The results are cached so this is fast after the first call.
612
      @return The canonicalized target port.
613
  */
614
  int port_get();
615
616
  /** Get the URL scheme.
617
      This is a reference, not allocated.
618
      @return A string_view to the scheme or an empty string_view if there is no valid URL.
619
  */
620
  std::string_view scheme_get();
621
  void             url_set(URL *url);
622
  void             url_set(std::string_view value);
623
624
  /// Check location of target host.
625
  /// @return @c true if the host was in the URL, @c false otherwise.
626
  /// @note This returns @c false if the host is missing.
627
  bool is_target_in_url() const;
628
629
  /// Check if a port was specified in the target.
630
  /// @return @c true if the port was part of the target.
631
  bool is_port_in_header() const;
632
633
  /// If the target is in the fields and not the URL, copy it to the @a url.
634
  /// If @a url is @c NULL the cached URL in this header is used.
635
  /// @note In the default case the copy is avoided if the cached URL already
636
  /// has the target. If @a url is non @c NULL the copy is always performed.
637
  void set_url_target_from_host_field(URL *url = nullptr);
638
639
  /// Mark the target cache as invalid.
640
  /// @internal Ugly but too many places currently that touch the
641
  /// header internals, they must be able to do this.
642
  void mark_target_dirty() const;
643
644
  HTTPStatus status_get() const;
645
  void       status_set(HTTPStatus status);
646
647
  std::string_view reason_get();
648
  void             reason_set(std::string_view value);
649
650
  void mark_early_data(bool flag = true) const;
651
  bool is_early_data() const;
652
653
  /** Parse an HTTP/1.x request header incrementally from a raw buffer.
654
   *
655
   * Parses input data into the header's request fields. Call repeatedly with the same @p parser
656
   * until a result other than @c ParseResult::CONT is returned. When @c ParseResult::DONE is
657
   * returned, the request method, URL, version, and header fields are set on this header.
658
   *
659
   * @param[in,out] parser                Parser state. Must be the same object on each call for a given message.
660
   * @param[in,out] start                 On entry, points to the first unparsed byte; on return,
661
   *                                       advanced past all consumed bytes.
662
   * @param[in]     end                   One past the last available byte of input.
663
   * @param[in]     eof                   @c true if no more data will follow @p end.
664
   * @param[in]     strict_uri_parsing    URI compliance level: @c 0 performs no compliance check; @c 1 rejects
665
   *                                       the URI unless every character is a valid RFC 3986 URI character; @c 2
666
   *                                       is more permissive, rejecting the URI only if it contains whitespace or
667
   *                                       non-printable characters. Other values behave like @c 0.
668
   * @param[in]     max_request_line_size Maximum byte length of the request line; exceeding it returns
669
   *                                       @c ParseResult::ERROR.
670
   * @param[in]     max_hdr_field_size    Maximum byte length of a single header field; exceeding it
671
   *                                       returns @c ParseResult::ERROR.
672
   *
673
   * @return @c ParseResult::DONE if a complete valid request header has been parsed;
674
   *         @c ParseResult::CONT if more data is required;
675
   *         @c ParseResult::ERROR on a protocol error or exceeded limit.
676
   *
677
   * @pre The header must be initialized with @c HTTPType::REQUEST polarity.
678
   *
679
   * @par Thread Safety
680
   *   Not thread-safe.
681
   */
682
  ParseResult parse_req(HTTPParser *parser, const char **start, const char *end, bool eof, int strict_uri_parsing = 0,
683
                        size_t max_request_line_size = UINT16_MAX, size_t max_hdr_field_size = 131070);
684
  ParseResult parse_resp(HTTPParser *parser, const char **start, const char *end, bool eof);
685
686
  /** Parse an HTTP/1.x request header incrementally from an @c IOBufferReader.
687
   *
688
   * Reads and consumes data from @p r, parsing it into the header's request fields. Call
689
   * repeatedly with the same @p parser until a result other than @c ParseResult::CONT is
690
   * returned. When @c ParseResult::DONE is returned, the request method, URL, version, and
691
   * header fields are set on this header.
692
   *
693
   * @param[in,out] parser                Parser state. Must be the same object on each call for a given message.
694
   * @param[in,out] r                     Source of input data; bytes consumed by the parser are removed from
695
   *                                       the reader.
696
   * @param[out]    bytes_used            Must be non-null; set to the number of bytes consumed from @p r.
697
   * @param[in]     eof                   @c true if no more data will be provided after what is currently
698
   *                                       available on @p r.
699
   * @param[in]     strict_uri_parsing    URI compliance level: @c 0 performs no compliance check; @c 1 rejects
700
   *                                       the URI unless every character is a valid RFC 3986 URI character; @c 2
701
   *                                       is more permissive, rejecting the URI only if it contains whitespace or
702
   *                                       non-printable characters. Other values behave like @c 0.
703
   * @param[in]     max_request_line_size Maximum byte length of the request line; exceeding it returns
704
   *                                       @c ParseResult::ERROR.
705
   * @param[in]     max_hdr_field_size    Maximum byte length of a single header field; exceeding it
706
   *                                       returns @c ParseResult::ERROR.
707
   *
708
   * @return @c ParseResult::DONE if a complete valid request header has been parsed;
709
   *         @c ParseResult::CONT if more data is required;
710
   *         @c ParseResult::ERROR on a protocol error or exceeded limit.
711
   *
712
   * @pre The header must be initialized with @c HTTPType::REQUEST polarity.
713
   *
714
   * @par Thread Safety
715
   *   Not thread-safe.
716
   */
717
  ParseResult parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof, int strict_uri_parsing = 0,
718
                        size_t max_request_line_size = UINT16_MAX, size_t max_hdr_field_size = UINT16_MAX);
719
  ParseResult parse_resp(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof);
720
721
  bool check_hdr_implements();
722
723
public:
724
  // Utility routines
725
  bool          is_cache_control_set(const char *cc_directive_wks);
726
  bool          is_pragma_no_cache_set();
727
  bool          is_keep_alive_set() const;
728
  bool          expect_final_response() const;
729
  HTTPKeepAlive keep_alive_get() const;
730
731
protected:
732
  /** Load the target cache.
733
      @see m_host, m_port, m_target_in_url
734
  */
735
  void _fill_target_cache() const;
736
  /** Test the cache and fill it if necessary.
737
      @internal In contrast to @c _fill_target_cache, this method
738
      is inline and checks whether the cache is already filled.
739
      @ _fill_target_cache @b always does a cache fill.
740
  */
741
  void _test_and_fill_target_cache() const;
742
  /** Null cached pointers/flags without touching the URL or heap.
743
      Shared between @c _reset_local_state() and @c reset(); URL and
744
      heap handling differ between those paths.
745
  */
746
  void _reset_local_fields();
747
  /** Null out members that reference the heap.
748
      Shared prologue for @c clear() and @c destroy(); ensures a reused
749
      HTTPHdr can't dereference a stale @c m_host_mime via @c host_get().
750
  */
751
  void _reset_local_state();
752
753
  static Arena *const USE_HDR_HEAP_MAGIC;
754
755
  // No gratuitous copies!
756
  HTTPHdr(const HTTPHdr &m)            = delete;
757
  HTTPHdr &operator=(const HTTPHdr &m) = delete;
758
759
private:
760
  friend class UrlPrintHack; // don't ask.
761
};
762
763
/*-------------------------------------------------------------------------
764
  -------------------------------------------------------------------------*/
765
766
inline int
767
HTTPHdr::valid() const
768
23.4k
{
769
23.4k
  return (m_http && m_mime && m_heap);
770
23.4k
}
771
772
/*-------------------------------------------------------------------------
773
  -------------------------------------------------------------------------*/
774
775
inline void
776
HTTPHdr::create(HTTPType polarity, HTTPVersion version, HdrHeap *heap)
777
24.5k
{
778
24.5k
  if (heap) {
779
0
    m_heap = heap;
780
24.5k
  } else if (!m_heap) {
781
24.5k
    m_heap = new_HdrHeap();
782
24.5k
  }
783
784
24.5k
  m_http = http_hdr_create(m_heap, polarity, version);
785
24.5k
  m_mime = m_http->m_fields_impl;
786
24.5k
}
787
788
inline void
789
HTTPHdr::_reset_local_fields()
790
24.5k
{
791
24.5k
  m_http           = nullptr;
792
24.5k
  m_mime           = nullptr;
793
24.5k
  m_host_mime      = nullptr;
794
24.5k
  m_host_length    = 0;
795
24.5k
  m_port           = 0;
796
24.5k
  m_target_cached  = false;
797
24.5k
  m_target_in_url  = false;
798
24.5k
  m_port_in_header = false;
799
24.5k
}
800
801
inline void
802
HTTPHdr::_reset_local_state()
803
24.5k
{
804
24.5k
  if (m_http && m_http->m_polarity == HTTPType::REQUEST) {
805
12.8k
    m_url_cached.clear();
806
12.8k
  }
807
24.5k
  _reset_local_fields();
808
24.5k
}
809
810
inline void
811
HTTPHdr::clear()
812
0
{
813
0
  _reset_local_state();
814
0
  this->HdrHeapSDKHandle::clear();
815
0
}
816
817
inline void
818
HTTPHdr::destroy()
819
24.5k
{
820
24.5k
  _reset_local_state();
821
24.5k
  this->HdrHeapSDKHandle::destroy();
822
24.5k
}
823
824
inline void
825
HTTPHdr::reset()
826
0
{
827
0
  m_heap = nullptr;
828
0
  m_url_cached.reset();
829
0
  _reset_local_fields();
830
0
}
831
832
/*-------------------------------------------------------------------------
833
  -------------------------------------------------------------------------*/
834
835
inline void
836
HTTPHdr::copy(const HTTPHdr *hdr)
837
0
{
838
0
  ink_assert(hdr->valid());
839
840
0
  if (valid()) {
841
0
    http_hdr_copy_onto(hdr->m_http, hdr->m_heap, m_http, m_heap, (m_heap != hdr->m_heap) ? true : false);
842
0
  } else {
843
0
    m_heap = new_HdrHeap();
844
0
    m_http = http_hdr_clone(hdr->m_http, hdr->m_heap, m_heap);
845
0
    m_mime = m_http->m_fields_impl;
846
0
  }
847
0
}
848
849
/*-------------------------------------------------------------------------
850
  -------------------------------------------------------------------------*/
851
852
inline void
853
HTTPHdr::copy_shallow(const HTTPHdr *hdr)
854
0
{
855
0
  ink_assert(hdr->valid());
856
857
0
  m_heap = hdr->m_heap;
858
0
  m_http = hdr->m_http;
859
0
  m_mime = hdr->m_mime;
860
861
0
  if (hdr->type_get() == HTTPType::REQUEST && m_url_cached.valid())
862
0
    m_url_cached.copy_shallow(&hdr->m_url_cached);
863
0
}
Unexecuted instantiation: HTTPHdr::copy_shallow(HTTPHdr const*)
Unexecuted instantiation: HTTPHdr::copy_shallow(HTTPHdr const*)
864
865
/*-------------------------------------------------------------------------
866
  -------------------------------------------------------------------------*/
867
868
inline int
869
HTTPHdr::print(char *buf, int bufsize, int *bufindex, int *dumpoffset) const
870
0
{
871
0
  ink_assert(valid());
872
0
  return http_hdr_print(m_http, buf, bufsize, bufindex, dumpoffset);
873
0
}
Unexecuted instantiation: HTTPHdr::print(char*, int, int*, int*) const
Unexecuted instantiation: HTTPHdr::print(char*, int, int*, int*) const
874
875
/*-------------------------------------------------------------------------
876
  -------------------------------------------------------------------------*/
877
878
inline void
879
HTTPHdr::_test_and_fill_target_cache() const
880
0
{
881
0
  if (!m_target_cached) {
882
0
    this->_fill_target_cache();
883
0
    return;
884
0
  }
885
886
  // If host came from the Host header (not URL), check for staleness by verifying
887
  // the current Host header value length matches what we expect from cached values.
888
0
  if (!m_target_in_url && m_host_mime != nullptr) {
889
0
    int expected_len = m_host_length;
890
0
    if (m_port_in_header && m_port > 0) {
891
      // Account for ":port" suffix in the raw Host header value.
892
0
      expected_len += 1; // colon
893
0
      if (m_port < 10) {
894
0
        expected_len += 1;
895
0
      } else if (m_port < 100) {
896
0
        expected_len += 2;
897
0
      } else if (m_port < 1000) {
898
0
        expected_len += 3;
899
0
      } else if (m_port < 10000) {
900
0
        expected_len += 4;
901
0
      } else {
902
0
        expected_len += 5;
903
0
      }
904
0
    }
905
0
    if (m_host_mime->m_len_value != expected_len) {
906
0
      this->_fill_target_cache();
907
0
    }
908
0
  }
909
0
}
910
911
/*-------------------------------------------------------------------------
912
  -------------------------------------------------------------------------*/
913
914
inline std::string_view
915
HTTPHdr::host_get() const
916
0
{
917
0
  this->_test_and_fill_target_cache();
918
0
  if (m_target_in_url) {
919
0
    return url_get()->host_get();
920
0
  } else if (m_host_mime) {
921
0
    return std::string_view{m_host_mime->m_ptr_value, static_cast<std::string_view::size_type>(m_host_length)};
922
0
  }
923
924
0
  return std::string_view{};
925
0
}
926
927
/*-------------------------------------------------------------------------
928
  -------------------------------------------------------------------------*/
929
930
inline int
931
HTTPHdr::port_get()
932
0
{
933
0
  this->_test_and_fill_target_cache();
934
0
  return m_port;
935
0
}
936
937
/*-------------------------------------------------------------------------
938
  -------------------------------------------------------------------------*/
939
940
inline bool
941
HTTPHdr::is_target_in_url() const
942
0
{
943
0
  this->_test_and_fill_target_cache();
944
0
  return m_target_in_url;
945
0
}
946
947
/*-------------------------------------------------------------------------
948
  -------------------------------------------------------------------------*/
949
950
inline bool
951
HTTPHdr::is_port_in_header() const
952
0
{
953
0
  this->_test_and_fill_target_cache();
954
0
  return m_port_in_header;
955
0
}
956
957
/*-------------------------------------------------------------------------
958
  -------------------------------------------------------------------------*/
959
960
inline void
961
HTTPHdr::mark_target_dirty() const
962
0
{
963
0
  m_target_cached = false;
964
0
}
965
/*-------------------------------------------------------------------------
966
  -------------------------------------------------------------------------*/
967
968
inline HTTPType
969
http_hdr_type_get(HTTPHdrImpl *hh)
970
0
{
971
0
  return (hh->m_polarity);
972
0
}
973
974
/*-------------------------------------------------------------------------
975
  -------------------------------------------------------------------------*/
976
977
inline HTTPType
978
HTTPHdr::type_get() const
979
0
{
980
0
  ink_assert(valid());
981
0
  return http_hdr_type_get(m_http);
982
0
}
Unexecuted instantiation: HTTPHdr::type_get() const
Unexecuted instantiation: HTTPHdr::type_get() const
983
984
/*-------------------------------------------------------------------------
985
  -------------------------------------------------------------------------*/
986
987
inline HTTPVersion
988
HTTPHdr::version_get() const
989
0
{
990
0
  ink_assert(valid());
991
0
  return m_http->m_version;
992
0
}
Unexecuted instantiation: HTTPHdr::version_get() const
Unexecuted instantiation: HTTPHdr::version_get() const
993
994
/*-------------------------------------------------------------------------
995
  -------------------------------------------------------------------------*/
996
997
inline static HTTPKeepAlive
998
is_header_keep_alive(const HTTPVersion &http_version, const MIMEField *con_hdr)
999
0
{
1000
0
  enum class ConToken {
1001
0
    NONE = 0,
1002
0
    KEEP_ALIVE,
1003
0
    CLOSE,
1004
0
  };
1005
1006
0
  auto          con_token  = ConToken::NONE;
1007
0
  HTTPKeepAlive keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
1008
  //    *unknown_tokens = false;
1009
1010
0
  if (con_hdr) {
1011
0
    if (con_hdr->value_get_index("keep-alive"sv) >= 0)
1012
0
      con_token = ConToken::KEEP_ALIVE;
1013
0
    else if (con_hdr->value_get_index("close"sv) >= 0)
1014
0
      con_token = ConToken::CLOSE;
1015
0
  }
1016
1017
0
  if (HTTP_1_0 == http_version) {
1018
0
    keep_alive = (con_token == ConToken::KEEP_ALIVE) ? (HTTPKeepAlive::KEEPALIVE) : (HTTPKeepAlive::NO_KEEPALIVE);
1019
0
  } else if (HTTP_1_1 == http_version) {
1020
    // We deviate from the spec here.  If the we got a response where
1021
    //   where there is no Connection header and the request 1.0 was
1022
    //   1.0 don't treat this as keep-alive since Netscape-Enterprise/3.6 SP1
1023
    //   server doesn't
1024
0
    keep_alive = ((con_token == ConToken::KEEP_ALIVE) || (con_token == ConToken::NONE && HTTP_1_1 == http_version)) ?
1025
0
                   (HTTPKeepAlive::KEEPALIVE) :
1026
0
                   (HTTPKeepAlive::NO_KEEPALIVE);
1027
0
  } else {
1028
0
    keep_alive = HTTPKeepAlive::NO_KEEPALIVE;
1029
0
  }
1030
0
  return (keep_alive);
1031
0
}
Unexecuted instantiation: fuzz_hpack.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HTTP2.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2Frame.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HPACK.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HTTP.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HdrHeap.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: URL.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: VersionConverter.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HeaderValidator.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: fuzz_http.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: fuzz_chunked.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpTunnel.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpConfig.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpSessionManager.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpSM.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpCacheSM.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpDebugNames.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpTransact.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpBodyFactory.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpTransactHeaders.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ConnectingEntry.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RegressionHttpTransact.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HostDB.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheControl.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ControlBase.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ControlMatcher.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: IPAllow.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ParentSelectionStrategy.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ParentSelection.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ParentRoundRobin.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ParentConsistentHash.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ProxySession.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ProxyTransaction.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ReverseProxy.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Transform.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: VirtualHost.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: NextHopSelectionStrategy.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: NextHopHealthStatus.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RemapProcessor.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RemapPlugins.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: AclFiltering.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: UrlRewrite.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: NextHopStrategyFactory.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: NextHopConsistentHash.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: NextHopRoundRobin.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RemapYamlConfig.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RemapConfig.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Cache.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheDir.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheDisk.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheHosting.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheHttp.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheProcessor.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheRead.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheShm.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheVC.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheWrite.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpTransactCache.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: PreservationTable.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RamCacheCLFUS.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RamCacheLRU.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: RamCacheS3FIFO.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Stripe.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: StripeSM.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: CacheEvacuateDocVC.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Log.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogAccess.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogBuffer.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogConfig.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogField.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogFile.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogFilter.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogFormat.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: LogObject.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: TransactionLogData.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: YamlLogConfig.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: YamlLogConfigDecoders.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: SplitDNS.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Socks.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: OCSPStapling.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: FetchSM.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: PluginHttpConnect.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpProxyServerMain.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: ProtocolProbeSessionAccept.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpSessionAccept.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http1ClientSession.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http1ClientTransaction.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2SessionAccept.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2ClientSession.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2CommonSession.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2ConnectionState.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2Stream.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2DebugNames.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http1ServerSession.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http1ServerTransaction.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http2ServerSession.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3SessionAccept.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3App.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3Session.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3Transaction.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3HeaderFramer.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: QPACK.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3DataFramer.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3HeaderVIOAdaptor.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http3SettingsHandler.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: Http09App.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: UnixNetProcessor.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: SNIActionPerformer.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HttpHookState.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
Unexecuted instantiation: HdrTSOnly.cc:is_header_keep_alive(HTTPVersion const&, MIMEField const*)
1032
1033
inline HTTPKeepAlive
1034
HTTPHdr::keep_alive_get() const
1035
0
{
1036
0
  HTTPKeepAlive    retval = HTTPKeepAlive::NO_KEEPALIVE;
1037
0
  const MIMEField *pc     = this->field_find(static_cast<std::string_view>(MIME_FIELD_PROXY_CONNECTION));
1038
0
  if (pc != nullptr) {
1039
0
    retval = is_header_keep_alive(this->version_get(), pc);
1040
0
  } else {
1041
0
    const MIMEField *c = this->field_find(static_cast<std::string_view>(MIME_FIELD_CONNECTION));
1042
0
    retval             = is_header_keep_alive(this->version_get(), c);
1043
0
  }
1044
0
  return retval;
1045
0
}
1046
1047
inline bool
1048
HTTPHdr::is_keep_alive_set() const
1049
0
{
1050
0
  return this->keep_alive_get() == HTTPKeepAlive::KEEPALIVE;
1051
0
}
1052
1053
/**
1054
   Check the status code is informational and expecting final response
1055
   - e.g. "100 Continue", "103 Early Hints"
1056
1057
   Please note that "101 Switching Protocol" is not included.
1058
 */
1059
inline bool
1060
HTTPHdr::expect_final_response() const
1061
0
{
1062
0
  switch (this->status_get()) {
1063
0
  case HTTPStatus::CONTINUE:
1064
0
  case HTTPStatus::EARLY_HINTS:
1065
0
    return true;
1066
0
  default:
1067
0
    return false;
1068
0
  }
1069
0
}
1070
1071
/*-------------------------------------------------------------------------
1072
  -------------------------------------------------------------------------*/
1073
1074
inline void
1075
HTTPHdr::version_set(HTTPVersion version)
1076
0
{
1077
0
  ink_assert(valid());
1078
0
  http_hdr_version_set(m_http, version);
1079
0
}
Unexecuted instantiation: HTTPHdr::version_set(HTTPVersion)
Unexecuted instantiation: HTTPHdr::version_set(HTTPVersion)
1080
1081
/*-------------------------------------------------------------------------
1082
  -------------------------------------------------------------------------*/
1083
1084
inline std::string_view
1085
HTTPHdr::method_get()
1086
0
{
1087
0
  ink_assert(valid());
1088
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1089
1090
0
  return http_hdr_method_get(m_http);
1091
0
}
Unexecuted instantiation: HTTPHdr::method_get()
Unexecuted instantiation: HTTPHdr::method_get()
1092
1093
inline int
1094
HTTPHdr::method_get_wksidx() const
1095
0
{
1096
0
  ink_assert(valid());
1097
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1098
1099
0
  return (m_http->u.req.m_method_wks_idx);
1100
0
}
Unexecuted instantiation: HTTPHdr::method_get_wksidx() const
Unexecuted instantiation: HTTPHdr::method_get_wksidx() const
1101
1102
/*-------------------------------------------------------------------------
1103
  -------------------------------------------------------------------------*/
1104
1105
inline void
1106
HTTPHdr::method_set(std::string_view value)
1107
0
{
1108
0
  ink_assert(valid());
1109
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1110
1111
0
  int method_wks_idx = hdrtoken_tokenize(value.data(), static_cast<int>(value.length()));
1112
0
  http_hdr_method_set(m_heap, m_http, value, method_wks_idx, true);
1113
0
}
Unexecuted instantiation: HTTPHdr::method_set(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: HTTPHdr::method_set(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
1114
1115
/*-------------------------------------------------------------------------
1116
  -------------------------------------------------------------------------*/
1117
1118
inline URL *
1119
HTTPHdr::url_create(URL *u)
1120
0
{
1121
0
  ink_assert(valid());
1122
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1123
1124
0
  u->set(this);
1125
0
  u->create(m_heap);
1126
0
  return (u);
1127
0
}
Unexecuted instantiation: HTTPHdr::url_create(URL*)
Unexecuted instantiation: HTTPHdr::url_create(URL*)
1128
1129
/*-------------------------------------------------------------------------
1130
  -------------------------------------------------------------------------*/
1131
1132
inline URL *
1133
HTTPHdr::url_get() const
1134
0
{
1135
0
  ink_assert(valid());
1136
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1137
1138
  // It's entirely possible that someone changed URL in our impl
1139
  // without updating the cached copy in the C++ layer.  Check
1140
  // to see if this happened before handing back the url
1141
1142
0
  URLImpl *real_impl = m_http->u.req.m_url_impl;
1143
0
  if (m_url_cached.m_url_impl != real_impl) {
1144
0
    m_url_cached.set(this);
1145
0
    m_url_cached.m_url_impl = real_impl;
1146
0
    this->mark_target_dirty();
1147
0
  }
1148
0
  return (&m_url_cached);
1149
0
}
1150
1151
/*-------------------------------------------------------------------------
1152
  -------------------------------------------------------------------------*/
1153
1154
inline URL *
1155
HTTPHdr::url_get(URL *url)
1156
0
{
1157
0
  ink_assert(valid());
1158
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1159
1160
0
  url->set(this); // attach refcount
1161
0
  url->m_url_impl = m_http->u.req.m_url_impl;
1162
0
  return (url);
1163
0
}
Unexecuted instantiation: HTTPHdr::url_get(URL*)
Unexecuted instantiation: HTTPHdr::url_get(URL*)
1164
1165
/*-------------------------------------------------------------------------
1166
  -------------------------------------------------------------------------*/
1167
1168
inline void
1169
HTTPHdr::url_set(URL *url)
1170
0
{
1171
0
  ink_assert(valid());
1172
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1173
1174
0
  URLImpl *url_impl = m_http->u.req.m_url_impl;
1175
0
  ::url_copy_onto(url->m_url_impl, url->m_heap, url_impl, m_heap, true);
1176
0
}
Unexecuted instantiation: HTTPHdr::url_set(URL*)
Unexecuted instantiation: HTTPHdr::url_set(URL*)
1177
1178
/*-------------------------------------------------------------------------
1179
  -------------------------------------------------------------------------*/
1180
1181
inline void
1182
HTTPHdr::url_set(std::string_view value)
1183
0
{
1184
0
  URLImpl *url_impl;
1185
1186
0
  ink_assert(valid());
1187
0
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1188
1189
0
  url_impl = m_http->u.req.m_url_impl;
1190
0
  ::url_clear(url_impl);
1191
0
  const char *str{value.data()};
1192
0
  ::url_parse(m_heap, url_impl, &str, str + value.length(), true);
1193
0
}
Unexecuted instantiation: HTTPHdr::url_set(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: HTTPHdr::url_set(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
1194
1195
/*-------------------------------------------------------------------------
1196
  -------------------------------------------------------------------------*/
1197
1198
inline HTTPStatus
1199
http_hdr_status_get(HTTPHdrImpl const *hh)
1200
0
{
1201
0
  ink_assert(hh->m_polarity == HTTPType::RESPONSE);
1202
0
  return (HTTPStatus)hh->u.resp.m_status;
1203
0
}
1204
1205
/*-------------------------------------------------------------------------
1206
  -------------------------------------------------------------------------*/
1207
1208
inline HTTPStatus
1209
HTTPHdr::status_get() const
1210
0
{
1211
0
  ink_assert(valid());
1212
1213
0
  if (m_http) {
1214
0
    ink_assert(m_http->m_polarity == HTTPType::RESPONSE);
1215
0
    return http_hdr_status_get(m_http);
1216
0
  }
1217
1218
0
  return HTTPStatus::NONE;
1219
0
}
Unexecuted instantiation: HTTPHdr::status_get() const
Unexecuted instantiation: HTTPHdr::status_get() const
1220
1221
/*-------------------------------------------------------------------------
1222
  -------------------------------------------------------------------------*/
1223
1224
inline void
1225
HTTPHdr::status_set(HTTPStatus status)
1226
0
{
1227
0
  ink_assert(valid());
1228
0
  ink_release_assert(m_http->m_polarity == HTTPType::RESPONSE);
1229
1230
0
  http_hdr_status_set(m_http, status);
1231
0
}
Unexecuted instantiation: HTTPHdr::status_set(HTTPStatus)
Unexecuted instantiation: HTTPHdr::status_set(HTTPStatus)
1232
1233
/*-------------------------------------------------------------------------
1234
  -------------------------------------------------------------------------*/
1235
1236
inline std::string_view
1237
HTTPHdr::reason_get()
1238
0
{
1239
0
  ink_assert(valid());
1240
0
  ink_assert(m_http->m_polarity == HTTPType::RESPONSE);
1241
1242
0
  return http_hdr_reason_get(m_http);
1243
0
}
Unexecuted instantiation: HTTPHdr::reason_get()
Unexecuted instantiation: HTTPHdr::reason_get()
1244
1245
/*-------------------------------------------------------------------------
1246
  -------------------------------------------------------------------------*/
1247
1248
inline void
1249
HTTPHdr::reason_set(std::string_view value)
1250
0
{
1251
0
  ink_assert(valid());
1252
0
  ink_release_assert(m_http->m_polarity == HTTPType::RESPONSE);
1253
1254
0
  http_hdr_reason_set(m_heap, m_http, value, true);
1255
0
}
Unexecuted instantiation: HTTPHdr::reason_set(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Unexecuted instantiation: HTTPHdr::reason_set(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
1256
1257
/*-------------------------------------------------------------------------
1258
  -------------------------------------------------------------------------*/
1259
1260
inline void
1261
HTTPHdr::mark_early_data(bool flag) const
1262
0
{
1263
0
  ink_assert(valid());
1264
0
  early_data = flag;
1265
0
}
Unexecuted instantiation: HTTPHdr::mark_early_data(bool) const
Unexecuted instantiation: HTTPHdr::mark_early_data(bool) const
1266
1267
/*-------------------------------------------------------------------------
1268
  -------------------------------------------------------------------------*/
1269
1270
inline bool
1271
HTTPHdr::is_early_data() const
1272
0
{
1273
0
  ink_assert(valid());
1274
0
  return early_data;
1275
0
}
Unexecuted instantiation: HTTPHdr::is_early_data() const
Unexecuted instantiation: HTTPHdr::is_early_data() const
1276
1277
/*-------------------------------------------------------------------------
1278
  -------------------------------------------------------------------------*/
1279
1280
inline ParseResult
1281
HTTPHdr::parse_req(HTTPParser *parser, const char **start, const char *end, bool eof, int strict_uri_parsing,
1282
                   size_t max_request_line_size, size_t max_hdr_field_size)
1283
11.7k
{
1284
11.7k
  ink_assert(valid());
1285
11.7k
  ink_assert(m_http->m_polarity == HTTPType::REQUEST);
1286
1287
11.7k
  return http_parser_parse_req(parser, m_heap, m_http, start, end, true, eof, strict_uri_parsing, max_request_line_size,
1288
11.7k
                               max_hdr_field_size);
1289
11.7k
}
1290
1291
/*-------------------------------------------------------------------------
1292
  -------------------------------------------------------------------------*/
1293
1294
inline ParseResult
1295
HTTPHdr::parse_resp(HTTPParser *parser, const char **start, const char *end, bool eof)
1296
11.7k
{
1297
11.7k
  ink_assert(valid());
1298
11.7k
  ink_assert(m_http->m_polarity == HTTPType::RESPONSE);
1299
1300
11.7k
  return http_parser_parse_resp(parser, m_heap, m_http, start, end, true, eof);
1301
11.7k
}
1302
1303
/*-------------------------------------------------------------------------
1304
  -------------------------------------------------------------------------*/
1305
1306
inline bool
1307
HTTPHdr::is_cache_control_set(const char *cc_directive_wks)
1308
0
{
1309
0
  ink_assert(valid());
1310
0
  ink_assert(hdrtoken_is_wks(cc_directive_wks));
1311
1312
0
  const HdrTokenHeapPrefix *prefix = hdrtoken_wks_to_prefix(cc_directive_wks);
1313
0
  ink_assert(prefix->wks_token_type == HdrTokenType::CACHE_CONTROL);
1314
1315
0
  uint32_t cc_mask = prefix->wks_type_specific.u.cache_control.cc_mask;
1316
0
  if (get_cooked_cc_mask() & cc_mask)
1317
0
    return (true);
1318
0
  else
1319
0
    return (false);
1320
0
}
Unexecuted instantiation: HTTPHdr::is_cache_control_set(char const*)
Unexecuted instantiation: HTTPHdr::is_cache_control_set(char const*)
1321
1322
/*-------------------------------------------------------------------------
1323
  -------------------------------------------------------------------------*/
1324
1325
inline bool
1326
HTTPHdr::is_pragma_no_cache_set()
1327
0
{
1328
0
  ink_assert(valid());
1329
0
  return (get_cooked_pragma_no_cache());
1330
0
}
Unexecuted instantiation: HTTPHdr::is_pragma_no_cache_set()
Unexecuted instantiation: HTTPHdr::is_pragma_no_cache_set()
1331
1332
inline char *
1333
HTTPHdr::url_string_get_ref(int *length)
1334
0
{
1335
0
  return this->url_string_get(USE_HDR_HEAP_MAGIC, length);
1336
0
}
1337
1338
inline std::string_view
1339
HTTPHdr::path_get()
1340
0
{
1341
0
  URL *url = this->url_get();
1342
0
  if (url) {
1343
0
    return url->path_get();
1344
0
  }
1345
0
  return {};
1346
0
}
1347
1348
inline std::string_view
1349
HTTPHdr::query_get()
1350
0
{
1351
0
  URL *url = this->url_get();
1352
0
  if (url) {
1353
0
    return url->query_get();
1354
0
  }
1355
0
  return std::string_view{};
1356
0
}
1357
1358
inline std::string_view
1359
HTTPHdr::fragment_get()
1360
0
{
1361
0
  URL *url = this->url_get();
1362
0
  if (url) {
1363
0
    return url->fragment_get();
1364
0
  }
1365
0
  return std::string_view{};
1366
0
}
1367
1368
inline std::string_view
1369
HTTPHdr::scheme_get()
1370
0
{
1371
0
  URL *url = this->url_get();
1372
0
  if (url) {
1373
0
    return url->scheme_get();
1374
0
  }
1375
0
  return std::string_view{};
1376
0
}
1377
1378
/*-------------------------------------------------------------------------
1379
  -------------------------------------------------------------------------*/
1380
1381
enum class CacheAltMagic : uint32_t {
1382
  ALIVE         = 0xabcddeed,
1383
  MARSHALED     = 0xdcbadeed,
1384
  MARSHALED_WKS = 0xdcbadeee, ///< Marshalled alternate followed by a uint64_t WKS identity.
1385
  DEAD          = 0xdeadeed,
1386
};
1387
1388
// struct HTTPCacheAlt
1389
struct HTTPCacheAlt {
1390
  HTTPCacheAlt();
1391
  void copy(HTTPCacheAlt *to_copy);
1392
  void copy_frag_offsets_from(HTTPCacheAlt *src);
1393
  void destroy();
1394
1395
  CacheAltMagic m_magic = CacheAltMagic::ALIVE;
1396
1397
  // Writeable is set to true is we reside
1398
  //  in a buffer owned by this structure.
1399
  // INVARIANT: if own the buffer this HttpCacheAlt
1400
  //   we also own the buffers for the request &
1401
  //   response headers
1402
  int32_t m_writeable     = 1;
1403
  int32_t m_unmarshal_len = -1;
1404
1405
  int32_t m_id  = -1;
1406
  int32_t m_rid = -1;
1407
1408
  int32_t m_object_key[sizeof(CryptoHash) / sizeof(int32_t)];
1409
  int32_t m_object_size[2];
1410
1411
  HTTPHdr m_request_hdr;
1412
  HTTPHdr m_response_hdr;
1413
1414
  time_t m_request_sent_time      = 0;
1415
  time_t m_response_received_time = 0;
1416
1417
  /// # of fragment offsets in this alternate.
1418
  /// @note This is one less than the number of fragments.
1419
  int m_frag_offset_count = 0;
1420
  /// Type of offset for a fragment.
1421
  using FragOffset = uint64_t;
1422
  /// Table of fragment offsets.
1423
  /// @note The offsets are forward looking so that frag[0] is the
1424
  /// first byte past the end of fragment 0 which is also the first
1425
  /// byte of fragment 1. For this reason there is no fragment offset
1426
  /// for the last fragment.
1427
  FragOffset *m_frag_offsets = nullptr;
1428
  /// # of fragment offsets built in to object.
1429
  static int constexpr N_INTEGRAL_FRAG_OFFSETS = 4;
1430
  /// Integral fragment offset table.
1431
  FragOffset m_integral_frag_offsets[N_INTEGRAL_FRAG_OFFSETS];
1432
1433
  // With clustering, our alt may be in cluster
1434
  //  incoming channel buffer, when we are
1435
  //  destroyed we decrement the refcount
1436
  //  on that buffer so that it gets destroyed
1437
  // We don't want to use a ref count ptr (Ptr<>)
1438
  //  since our ownership model requires explicit
1439
  //  destroys and ref count pointers defeat this
1440
  RefCountObj *m_ext_buffer = nullptr;
1441
};
1442
1443
class HTTPInfo
1444
{
1445
public:
1446
  using FragOffset = HTTPCacheAlt::FragOffset; ///< Import type.
1447
1448
  HTTPCacheAlt *m_alt = nullptr;
1449
1450
4
  HTTPInfo() {}
1451
0
  ~HTTPInfo() { clear(); }
1452
  void
1453
  clear()
1454
0
  {
1455
0
    m_alt = nullptr;
1456
0
  }
1457
  bool
1458
  valid() const
1459
0
  {
1460
0
    return m_alt != nullptr;
1461
0
  }
1462
1463
  void create();
1464
  void destroy();
1465
1466
  void copy(HTTPInfo *to_copy);
1467
  void
1468
  copy_shallow(HTTPInfo *info)
1469
0
  {
1470
0
    m_alt = info->m_alt;
1471
0
  }
1472
  void      copy_frag_offsets_from(HTTPInfo *src);
1473
  HTTPInfo &operator=(const HTTPInfo &m);
1474
1475
  int        marshal_length();
1476
  int        marshal(char *buf, int len);
1477
  static int unmarshal(char *buf, int len, RefCountObj *block_ref);
1478
  static int unmarshal_v24_1(char *buf, int len, RefCountObj *block_ref);
1479
  void       set_buffer_reference(RefCountObj *block_ref);
1480
  int        get_handle(char *buf, int len);
1481
1482
  int32_t
1483
  id_get() const
1484
0
  {
1485
0
    return m_alt->m_id;
1486
0
  }
1487
  int32_t
1488
  rid_get()
1489
0
  {
1490
0
    return m_alt->m_rid;
1491
0
  }
1492
1493
  void
1494
  id_set(int32_t id)
1495
0
  {
1496
0
    m_alt->m_id = id;
1497
0
  }
1498
  void
1499
  rid_set(int32_t id)
1500
0
  {
1501
0
    m_alt->m_rid = id;
1502
0
  }
1503
1504
  CryptoHash object_key_get();
1505
  void       object_key_get(CryptoHash *);
1506
  bool       compare_object_key(const CryptoHash *);
1507
  int64_t    object_size_get();
1508
1509
  void
1510
  request_get(HTTPHdr *hdr)
1511
0
  {
1512
0
    hdr->copy_shallow(&m_alt->m_request_hdr);
1513
0
  }
1514
  void
1515
  response_get(HTTPHdr *hdr)
1516
0
  {
1517
0
    hdr->copy_shallow(&m_alt->m_response_hdr);
1518
0
  }
1519
1520
  HTTPHdr *
1521
  request_get()
1522
0
  {
1523
0
    return &m_alt->m_request_hdr;
1524
0
  }
1525
  HTTPHdr *
1526
  response_get()
1527
0
  {
1528
0
    return &m_alt->m_response_hdr;
1529
0
  }
1530
1531
  URL *
1532
  request_url_get(URL *url = nullptr)
1533
0
  {
1534
0
    return m_alt->m_request_hdr.url_get(url);
1535
0
  }
1536
1537
  time_t
1538
  request_sent_time_get()
1539
0
  {
1540
0
    return m_alt->m_request_sent_time;
1541
0
  }
1542
  time_t
1543
  response_received_time_get()
1544
0
  {
1545
0
    return m_alt->m_response_received_time;
1546
0
  }
1547
1548
  void object_key_set(CryptoHash &hash);
1549
  void object_size_set(int64_t size);
1550
1551
  void
1552
  request_set(const HTTPHdr *req)
1553
0
  {
1554
0
    m_alt->m_request_hdr.copy(req);
1555
0
  }
1556
  void
1557
  response_set(const HTTPHdr *resp)
1558
0
  {
1559
0
    m_alt->m_response_hdr.copy(resp);
1560
0
  }
1561
1562
  void
1563
  request_sent_time_set(time_t t)
1564
0
  {
1565
0
    m_alt->m_request_sent_time = t;
1566
0
  }
1567
  void
1568
  response_received_time_set(time_t t)
1569
0
  {
1570
0
    m_alt->m_response_received_time = t;
1571
0
  }
1572
1573
  /// Get the fragment table.
1574
  FragOffset *get_frag_table();
1575
  /// Get the # of fragment offsets
1576
  /// @note This is the size of the fragment offset table, and one less
1577
  /// than the actual # of fragments.
1578
  int get_frag_offset_count();
1579
  /// Add an @a offset to the end of the fragment offset table.
1580
  void push_frag_offset(FragOffset offset);
1581
1582
  // Sanity check functions
1583
  static bool check_marshalled(char *buf, int len);
1584
1585
private:
1586
  HTTPInfo(const HTTPInfo &h);
1587
};
1588
1589
inline void
1590
HTTPInfo::destroy()
1591
0
{
1592
0
  if (m_alt) {
1593
0
    if (m_alt->m_writeable) {
1594
0
      m_alt->destroy();
1595
0
    } else if (m_alt->m_ext_buffer) {
1596
0
      if (m_alt->m_ext_buffer->refcount_dec() == 0) {
1597
0
        m_alt->m_ext_buffer->free();
1598
0
      }
1599
0
    }
1600
0
  }
1601
0
  clear();
1602
0
}
1603
1604
inline HTTPInfo &
1605
HTTPInfo::operator=(const HTTPInfo &m)
1606
0
{
1607
0
  m_alt = m.m_alt;
1608
0
  return *this;
1609
0
}
1610
1611
inline CryptoHash
1612
HTTPInfo::object_key_get()
1613
0
{
1614
0
  CryptoHash val;
1615
0
  int32_t   *pi = reinterpret_cast<int32_t *>(&val);
1616
0
1617
0
  memcpy(pi, m_alt->m_object_key, sizeof(CryptoHash));
1618
0
1619
0
  return val;
1620
0
}
1621
1622
inline void
1623
HTTPInfo::object_key_get(CryptoHash *hash)
1624
0
{
1625
0
  int32_t *pi = reinterpret_cast<int32_t *>(hash);
1626
0
  memcpy(pi, m_alt->m_object_key, CRYPTO_HASH_SIZE);
1627
0
}
Unexecuted instantiation: HTTPInfo::object_key_get(ts::CryptoHash*)
Unexecuted instantiation: HTTPInfo::object_key_get(ts::CryptoHash*)
1628
1629
inline bool
1630
HTTPInfo::compare_object_key(const CryptoHash *hash)
1631
0
{
1632
0
  int32_t const *pi = reinterpret_cast<int32_t const *>(hash);
1633
0
  return memcmp(pi, m_alt->m_object_key, CRYPTO_HASH_SIZE) == 0;
1634
0
}
Unexecuted instantiation: HTTPInfo::compare_object_key(ts::CryptoHash const*)
Unexecuted instantiation: HTTPInfo::compare_object_key(ts::CryptoHash const*)
1635
1636
inline int64_t
1637
HTTPInfo::object_size_get()
1638
0
{
1639
0
  int64_t  val = 0; // make gcc shut up.
1640
0
  int32_t *pi  = reinterpret_cast<int32_t *>(&val);
1641
0
1642
0
  pi[0] = m_alt->m_object_size[0];
1643
0
  pi[1] = m_alt->m_object_size[1];
1644
0
  return val;
1645
0
}
1646
1647
inline void
1648
HTTPInfo::object_key_set(CryptoHash &hash)
1649
0
{
1650
0
  int32_t *pi = reinterpret_cast<int32_t *>(&hash);
1651
0
  memcpy(m_alt->m_object_key, pi, CRYPTO_HASH_SIZE);
1652
0
}
Unexecuted instantiation: HTTPInfo::object_key_set(ts::CryptoHash&)
Unexecuted instantiation: HTTPInfo::object_key_set(ts::CryptoHash&)
1653
1654
inline void
1655
HTTPInfo::object_size_set(int64_t size)
1656
0
{
1657
0
  int32_t *pi             = reinterpret_cast<int32_t *>(&size);
1658
0
  m_alt->m_object_size[0] = pi[0];
1659
0
  m_alt->m_object_size[1] = pi[1];
1660
0
}
1661
1662
inline HTTPInfo::FragOffset *
1663
HTTPInfo::get_frag_table()
1664
0
{
1665
0
  return m_alt ? m_alt->m_frag_offsets : nullptr;
1666
0
}
1667
1668
inline int
1669
HTTPInfo::get_frag_offset_count()
1670
0
{
1671
0
  return m_alt ? m_alt->m_frag_offset_count : 0;
1672
0
}