xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/balsa/balsa_headers.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // A lightweight implementation for storing HTTP headers.
6 
7 #ifndef QUICHE_BALSA_BALSA_HEADERS_H_
8 #define QUICHE_BALSA_BALSA_HEADERS_H_
9 
10 #include <cstddef>
11 #include <cstring>
12 #include <functional>
13 #include <iterator>
14 #include <memory>
15 #include <optional>
16 #include <ostream>
17 #include <string>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/container/flat_hash_map.h"
22 #include "absl/container/flat_hash_set.h"
23 #include "absl/memory/memory.h"
24 #include "absl/strings/ascii.h"
25 #include "absl/strings/match.h"
26 #include "absl/strings/string_view.h"
27 #include "quiche/balsa/balsa_enums.h"
28 #include "quiche/balsa/header_api.h"
29 #include "quiche/balsa/standard_header_map.h"
30 #include "quiche/common/platform/api/quiche_bug_tracker.h"
31 #include "quiche/common/platform/api/quiche_export.h"
32 #include "quiche/common/platform/api/quiche_logging.h"
33 #include "quiche/common/quiche_callbacks.h"
34 
35 namespace gfe2 {
36 class Http2HeaderValidator;
37 }  // namespace gfe2
38 
39 namespace quiche {
40 
41 namespace test {
42 class BalsaHeadersTestPeer;
43 }  // namespace test
44 
45 // WARNING:
46 // Note that -no- char* returned by any function in this
47 // file is null-terminated.
48 
49 // This class exists to service the specific needs of BalsaHeaders.
50 //
51 // Functional goals:
52 //   1) provide a backing-store for all of the StringPieces that BalsaHeaders
53 //      returns. Every StringPiece returned from BalsaHeaders should remain
54 //      valid until the BalsaHeader's object is cleared, or the header-line is
55 //      erased.
56 //   2) provide a backing-store for BalsaFrame, which requires contiguous memory
57 //      for its fast-path parsing functions. Note that the cost of copying is
58 //      less than the cost of requiring the parser to do slow-path parsing, as
59 //      it would have to check for bounds every byte, instead of every 16 bytes.
60 //
61 // This class is optimized for the case where headers are stored in one of two
62 // buffers. It doesn't make a lot of effort to densely pack memory-- in fact,
63 // it -may- be somewhat memory inefficient. This possible inefficiency allows a
64 // certain simplicity of implementation and speed which makes it worthwhile.
65 // If, in the future, better memory density is required, it should be possible
66 // to reuse the abstraction presented by this object to achieve those goals.
67 //
68 // In the most common use-case, this memory inefficiency should be relatively
69 // small.
70 //
71 // Alternate implementations of BalsaBuffer may include:
72 //  - vector of strings, one per header line (similar to HTTPHeaders)
73 //  - densely packed strings:
74 //    - keep a sorted array/map of free-space linked lists or numbers.
75 //      - use the entry that most closely first your needs.
76 //    - at this point, perhaps just use a vector of strings, and let
77 //      the allocator do the right thing.
78 //
79 class QUICHE_EXPORT BalsaBuffer {
80  public:
81   static constexpr size_t kDefaultBlocksize = 4096;
82 
83   // The BufferBlock is a structure used internally by the
84   // BalsaBuffer class to store the base buffer pointers to
85   // each block, as well as the important metadata for buffer
86   // sizes and bytes free. It *may* be possible to replace this
87   // with a vector<char>, but it's unclear whether moving a vector
88   // can invalidate pointers into it. LWG issue 2321 proposes to fix this.
89   struct QUICHE_EXPORT BufferBlock {
90    public:
91     std::unique_ptr<char[]> buffer;
92     size_t buffer_size = 0;
93     size_t bytes_free = 0;
94 
bytes_usedBufferBlock95     size_t bytes_used() const { return buffer_size - bytes_free; }
start_of_unused_bytesBufferBlock96     char* start_of_unused_bytes() const { return buffer.get() + bytes_used(); }
97 
BufferBlockBufferBlock98     BufferBlock() {}
99 
BufferBlockBufferBlock100     BufferBlock(std::unique_ptr<char[]> buf, size_t size, size_t free)
101         : buffer(std::move(buf)), buffer_size(size), bytes_free(free) {}
102 
103     BufferBlock(const BufferBlock&) = delete;
104     BufferBlock& operator=(const BufferBlock&) = delete;
105     BufferBlock(BufferBlock&&) = default;
106     BufferBlock& operator=(BufferBlock&&) = default;
107 
108     // Note: allocating a fresh buffer even if we could reuse an old one may let
109     // us shed memory, and invalidates old StringPieces (making them easier to
110     // catch with asan).
CopyFromBufferBlock111     void CopyFrom(const BufferBlock& rhs) {
112       QUICHE_DCHECK(this != &rhs);
113       buffer_size = rhs.buffer_size;
114       bytes_free = rhs.bytes_free;
115       if (rhs.buffer == nullptr) {
116         buffer = nullptr;
117       } else {
118         buffer = std::make_unique<char[]>(buffer_size);
119         memcpy(buffer.get(), rhs.buffer.get(), rhs.bytes_used());
120       }
121     }
122   };
123 
124   typedef std::vector<BufferBlock> Blocks;
125 
BalsaBuffer()126   BalsaBuffer()
127       : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {}
128 
BalsaBuffer(size_t blocksize)129   explicit BalsaBuffer(size_t blocksize)
130       : blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {}
131 
132   BalsaBuffer(const BalsaBuffer&) = delete;
133   BalsaBuffer& operator=(const BalsaBuffer&) = delete;
134   BalsaBuffer(BalsaBuffer&&) = default;
135   BalsaBuffer& operator=(BalsaBuffer&&) = default;
136 
137   // Returns the total amount of memory reserved by the buffer blocks.
GetTotalBufferBlockSize()138   size_t GetTotalBufferBlockSize() const {
139     size_t buffer_size = 0;
140     for (Blocks::const_iterator iter = blocks_.begin(); iter != blocks_.end();
141          ++iter) {
142       buffer_size += iter->buffer_size;
143     }
144     return buffer_size;
145   }
146 
147   // Returns the total amount of memory used by the buffer blocks.
GetTotalBytesUsed()148   size_t GetTotalBytesUsed() const {
149     size_t bytes_used = 0;
150     for (const auto& b : blocks_) {
151       bytes_used += b.bytes_used();
152     }
153     return bytes_used;
154   }
155 
GetPtr(Blocks::size_type block_idx)156   const char* GetPtr(Blocks::size_type block_idx) const {
157     QUICHE_DCHECK_LT(block_idx, blocks_.size())
158         << block_idx << ", " << blocks_.size();
159     return block_idx >= blocks_.size() ? nullptr
160                                        : blocks_[block_idx].buffer.get();
161   }
162 
GetPtr(Blocks::size_type block_idx)163   char* GetPtr(Blocks::size_type block_idx) {
164     QUICHE_DCHECK_LT(block_idx, blocks_.size())
165         << block_idx << ", " << blocks_.size();
166     return block_idx >= blocks_.size() ? nullptr
167                                        : blocks_[block_idx].buffer.get();
168   }
169 
170   // This function is different from Reserve(), as it ensures that the data
171   // stored via subsequent calls to this function are all contiguous (and in
172   // the order in which these writes happened). This is essentially the same
173   // as a string append.
174   //
175   // You may call this function at any time between object
176   // construction/Clear(), and the calling of the
177   // NoMoreWriteToContiguousBuffer() function.
178   //
179   // You must not call this function after the NoMoreWriteToContiguousBuffer()
180   // function is called, unless a Clear() has been called since.
181   // If you do, the program will abort().
182   //
183   // This condition is placed upon this code so that calls to Reserve() can
184   // append to the buffer in the first block safely, and without invaliding
185   // the StringPiece which it returns.
186   //
187   // This function's main intended user is the BalsaFrame class, which,
188   // for reasons of efficiency, requires that the buffer from which it parses
189   // the headers be contiguous.
190   //
WriteToContiguousBuffer(absl::string_view sp)191   void WriteToContiguousBuffer(absl::string_view sp) {
192     if (sp.empty()) {
193       return;
194     }
195     QUICHE_CHECK(can_write_to_contiguous_buffer_);
196 
197     if (blocks_.empty()) {
198       blocks_.push_back(AllocBlock());
199     }
200 
201     QUICHE_DCHECK_GE(blocks_.size(), 1u);
202     if (blocks_[0].buffer == nullptr && sp.size() <= blocksize_) {
203       blocks_[0] = AllocBlock();
204       memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
205     } else if (blocks_[0].bytes_free < sp.size()) {
206       // the first block isn't big enough, resize it.
207       const size_t old_storage_size_used = blocks_[0].bytes_used();
208       // Increase to at least 2*old_storage_size_used; if sp.size() is larger,
209       // we'll increase by that amount.
210       const size_t new_storage_size =
211           old_storage_size_used + (old_storage_size_used < sp.size()
212                                        ? sp.size()
213                                        : old_storage_size_used);
214       std::unique_ptr<char[]> new_storage{new char[new_storage_size]};
215       char* old_storage = blocks_[0].buffer.get();
216       if (old_storage_size_used != 0u) {
217         memcpy(new_storage.get(), old_storage, old_storage_size_used);
218       }
219       memcpy(new_storage.get() + old_storage_size_used, sp.data(), sp.size());
220       blocks_[0].buffer = std::move(new_storage);
221       blocks_[0].bytes_free = new_storage_size - old_storage_size_used;
222       blocks_[0].buffer_size = new_storage_size;
223     } else {
224       memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
225     }
226     blocks_[0].bytes_free -= sp.size();
227   }
228 
NoMoreWriteToContiguousBuffer()229   void NoMoreWriteToContiguousBuffer() {
230     can_write_to_contiguous_buffer_ = false;
231   }
232 
233   // Reserves "permanent" storage of the size indicated. Returns a pointer to
234   // the beginning of that storage, and assigns the index of the block used to
235   // block_buffer_idx. This function uses the first block IFF the
236   // NoMoreWriteToContiguousBuffer function has been called since the last
237   // Clear/Construction.
Reserve(size_t size,Blocks::size_type * block_buffer_idx)238   char* Reserve(size_t size, Blocks::size_type* block_buffer_idx) {
239     if (blocks_.empty()) {
240       blocks_.push_back(AllocBlock());
241     }
242 
243     // There should always be a 'first_block', even if it
244     // contains nothing.
245     QUICHE_DCHECK_GE(blocks_.size(), 1u);
246     BufferBlock* block = nullptr;
247     Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
248     for (; block_idx < blocks_.size(); ++block_idx) {
249       if (blocks_[block_idx].bytes_free >= size) {
250         block = &blocks_[block_idx];
251         break;
252       }
253     }
254     if (block == nullptr) {
255       if (blocksize_ < size) {
256         blocks_.push_back(AllocCustomBlock(size));
257       } else {
258         blocks_.push_back(AllocBlock());
259       }
260       block = &blocks_.back();
261     }
262 
263     char* storage = block->start_of_unused_bytes();
264     block->bytes_free -= size;
265     if (block_buffer_idx != nullptr) {
266       *block_buffer_idx = block_idx;
267     }
268     return storage;
269   }
270 
Clear()271   void Clear() {
272     blocks_.clear();
273     blocks_.shrink_to_fit();
274     can_write_to_contiguous_buffer_ = true;
275   }
276 
CopyFrom(const BalsaBuffer & b)277   void CopyFrom(const BalsaBuffer& b) {
278     blocks_.resize(b.blocks_.size());
279     for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
280       blocks_[i].CopyFrom(b.blocks_[i]);
281     }
282     blocksize_ = b.blocksize_;
283     can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
284   }
285 
StartOfFirstBlock()286   const char* StartOfFirstBlock() const {
287     QUICHE_BUG_IF(bug_if_1182_1, blocks_.empty())
288         << "First block not allocated yet!";
289     return blocks_.empty() ? nullptr : blocks_[0].buffer.get();
290   }
291 
EndOfFirstBlock()292   const char* EndOfFirstBlock() const {
293     QUICHE_BUG_IF(bug_if_1182_2, blocks_.empty())
294         << "First block not allocated yet!";
295     return blocks_.empty() ? nullptr : blocks_[0].start_of_unused_bytes();
296   }
297 
GetReadableBytesOfFirstBlock()298   size_t GetReadableBytesOfFirstBlock() const {
299     return blocks_.empty() ? 0 : blocks_[0].bytes_used();
300   }
301 
can_write_to_contiguous_buffer()302   bool can_write_to_contiguous_buffer() const {
303     return can_write_to_contiguous_buffer_;
304   }
blocksize()305   size_t blocksize() const { return blocksize_; }
num_blocks()306   Blocks::size_type num_blocks() const { return blocks_.size(); }
buffer_size(size_t idx)307   size_t buffer_size(size_t idx) const { return blocks_[idx].buffer_size; }
bytes_used(size_t idx)308   size_t bytes_used(size_t idx) const { return blocks_[idx].bytes_used(); }
309 
310  private:
AllocBlock()311   BufferBlock AllocBlock() { return AllocCustomBlock(blocksize_); }
312 
AllocCustomBlock(size_t blocksize)313   BufferBlock AllocCustomBlock(size_t blocksize) {
314     return BufferBlock{std::make_unique<char[]>(blocksize), blocksize,
315                        blocksize};
316   }
317 
318   // A container of BufferBlocks
319   Blocks blocks_;
320 
321   // The default allocation size for a block.
322   // In general, blocksize_ bytes will be allocated for
323   // each buffer.
324   size_t blocksize_;
325 
326   // If set to true, then the first block cannot be used for Reserve() calls as
327   // the WriteToContiguous... function will modify the base pointer for this
328   // block, and the Reserve() calls need to be sure that the base pointer will
329   // not be changing in order to provide the user with StringPieces which
330   // continue to be valid.
331   bool can_write_to_contiguous_buffer_;
332 };
333 
334 ////////////////////////////////////////////////////////////////////////////////
335 
336 // All of the functions in the BalsaHeaders class use string pieces, by either
337 // using the StringPiece class, or giving an explicit size and char* (as these
338 // are the native representation for these string pieces).
339 // This is done for several reasons.
340 //  1) This minimizes copying/allocation/deallocation as compared to using
341 //  string parameters
342 //  2) This reduces the number of strlen() calls done (as the length of any
343 //  string passed in is relatively likely to be known at compile time, and for
344 //  those strings passed back we obviate the need for a strlen() to determine
345 //  the size of new storage allocations if a new allocation is required.
346 //  3) This class attempts to store all of its data in two linear buffers in
347 //  order to enhance the speed of parsing and writing out to a buffer. As a
348 //  result, many string pieces are -not- terminated by '\0', and are not
349 //  c-strings.  Since this is the case, we must delineate the length of the
350 //  string explicitly via a length.
351 //
352 //  WARNING:  The side effect of using StringPiece is that if the underlying
353 //  buffer changes (due to modifying the headers) the StringPieces which point
354 //  to the data which was modified, may now contain "garbage", and should not
355 //  be dereferenced.
356 //  For example, If you fetch some component of the first-line, (request or
357 //  response), and then you modify the first line, the StringPieces you
358 //  originally received from the original first-line may no longer be valid).
359 //
360 //  StringPieces pointing to pieces of header lines which have not been
361 //  erased() or modified should be valid until the object is cleared or
362 //  destroyed.
363 //
364 //  Key comparisons are case-insensitive.
365 
366 class QUICHE_EXPORT BalsaHeaders : public HeaderApi {
367  public:
368   // Each header line is parsed into a HeaderLineDescription, which maintains
369   // pointers into the BalsaBuffer.
370   //
371   // Succinctly describes one header line as indices into a buffer.
372   struct QUICHE_EXPORT HeaderLineDescription {
HeaderLineDescriptionHeaderLineDescription373     HeaderLineDescription(size_t first_character_index, size_t key_end_index,
374                           size_t value_begin_index, size_t last_character_index,
375                           size_t buffer_base_index)
376         : first_char_idx(first_character_index),
377           key_end_idx(key_end_index),
378           value_begin_idx(value_begin_index),
379           last_char_idx(last_character_index),
380           buffer_base_idx(buffer_base_index),
381           skip(false) {}
382 
HeaderLineDescriptionHeaderLineDescription383     HeaderLineDescription()
384         : first_char_idx(0),
385           key_end_idx(0),
386           value_begin_idx(0),
387           last_char_idx(0),
388           buffer_base_idx(0),
389           skip(false) {}
390 
KeyLengthHeaderLineDescription391     size_t KeyLength() const {
392       QUICHE_DCHECK_GE(key_end_idx, first_char_idx);
393       return key_end_idx - first_char_idx;
394     }
ValuesLengthHeaderLineDescription395     size_t ValuesLength() const {
396       QUICHE_DCHECK_GE(last_char_idx, value_begin_idx);
397       return last_char_idx - value_begin_idx;
398     }
399 
400     size_t first_char_idx;
401     size_t key_end_idx;
402     size_t value_begin_idx;
403     size_t last_char_idx;
404     BalsaBuffer::Blocks::size_type buffer_base_idx;
405     bool skip;
406   };
407 
408   using HeaderTokenList = std::vector<absl::string_view>;
409 
410   // An iterator for walking through all the header lines.
411   class const_header_lines_iterator;
412 
413   // An iterator that only stops at lines with a particular key
414   // (case-insensitive).  See also GetIteratorForKey.
415   //
416   // Check against header_lines_key_end() to determine when iteration is
417   // finished. lines().end() will also work.
418   class const_header_lines_key_iterator;
419 
420   // A simple class that can be used in a range-based for loop.
421   template <typename IteratorType>
422   class QUICHE_EXPORT iterator_range {
423    public:
424     using iterator = IteratorType;
425     using const_iterator = IteratorType;
426     using value_type = typename std::iterator_traits<IteratorType>::value_type;
427 
iterator_range(IteratorType begin_iterator,IteratorType end_iterator)428     iterator_range(IteratorType begin_iterator, IteratorType end_iterator)
429         : begin_iterator_(std::move(begin_iterator)),
430           end_iterator_(std::move(end_iterator)) {}
431 
begin()432     IteratorType begin() const { return begin_iterator_; }
end()433     IteratorType end() const { return end_iterator_; }
434 
435    private:
436     IteratorType begin_iterator_, end_iterator_;
437   };
438 
439   // Set of names of headers that might have multiple values.
440   // CoalesceOption::kCoalesce can be used to match Envoy behavior in
441   // WriteToBuffer().
442   using MultivaluedHeadersSet =
443       absl::flat_hash_set<absl::string_view, StringPieceCaseHash,
444                           StringPieceCaseEqual>;
445 
446   // Map of key => vector<value>, where vector contains ordered list of all
447   // values for |key| (ignoring the casing).
448   using MultivaluedHeadersValuesMap =
449       absl::flat_hash_map<absl::string_view, std::vector<absl::string_view>,
450                           StringPieceCaseHash, StringPieceCaseEqual>;
451 
BalsaHeaders()452   BalsaHeaders()
453       : balsa_buffer_(4096),
454         content_length_(0),
455         content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
456         parsed_response_code_(0),
457         firstline_buffer_base_idx_(0),
458         whitespace_1_idx_(0),
459         non_whitespace_1_idx_(0),
460         whitespace_2_idx_(0),
461         non_whitespace_2_idx_(0),
462         whitespace_3_idx_(0),
463         non_whitespace_3_idx_(0),
464         whitespace_4_idx_(0),
465         transfer_encoding_is_chunked_(false) {}
466 
BalsaHeaders(size_t bufsize)467   explicit BalsaHeaders(size_t bufsize)
468       : balsa_buffer_(bufsize),
469         content_length_(0),
470         content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
471         parsed_response_code_(0),
472         firstline_buffer_base_idx_(0),
473         whitespace_1_idx_(0),
474         non_whitespace_1_idx_(0),
475         whitespace_2_idx_(0),
476         non_whitespace_2_idx_(0),
477         whitespace_3_idx_(0),
478         non_whitespace_3_idx_(0),
479         whitespace_4_idx_(0),
480         transfer_encoding_is_chunked_(false) {}
481 
482   // Copying BalsaHeaders is expensive, so require that it be visible.
483   BalsaHeaders(const BalsaHeaders&) = delete;
484   BalsaHeaders& operator=(const BalsaHeaders&) = delete;
485   BalsaHeaders(BalsaHeaders&&) = default;
486   BalsaHeaders& operator=(BalsaHeaders&&) = default;
487 
488   // Returns a range that represents all of the header lines.
489   iterator_range<const_header_lines_iterator> lines() const;
490 
491   // Returns an iterator range consisting of the header lines matching key.
492   // String backing 'key' must remain valid for lifetime of range.
493   iterator_range<const_header_lines_key_iterator> lines(
494       absl::string_view key) const;
495 
496   // Returns a forward-only iterator that only stops at lines matching key.
497   // String backing 'key' must remain valid for lifetime of iterator.
498   //
499   // Check returned iterator against header_lines_key_end() to determine when
500   // iteration is finished.
501   //
502   // Consider calling lines(key)--it may be more readable.
503   const_header_lines_key_iterator GetIteratorForKey(
504       absl::string_view key) const;
505 
506   const_header_lines_key_iterator header_lines_key_end() const;
507 
508   void erase(const const_header_lines_iterator& it);
509 
510   void Clear();
511 
512   // Explicit copy functions to avoid risk of accidental copies.
Copy()513   BalsaHeaders Copy() const {
514     BalsaHeaders copy;
515     copy.CopyFrom(*this);
516     return copy;
517   }
518   void CopyFrom(const BalsaHeaders& other);
519 
520   // Replaces header entries with key 'key' if they exist, or appends
521   // a new header if none exist.  See 'AppendHeader' below for additional
522   // comments about ContentLength and TransferEncoding headers. Note that this
523   // will allocate new storage every time that it is called.
524   void ReplaceOrAppendHeader(absl::string_view key,
525                              absl::string_view value) override;
526 
527   // Append a new header entry to the header object. Clients who wish to append
528   // Content-Length header should use SetContentLength() method instead of
529   // adding the content length header using AppendHeader (manually adding the
530   // content length header will not update the content_length_ and
531   // content_length_status_ values).
532   // Similarly, clients who wish to add or remove the transfer encoding header
533   // in order to apply or remove chunked encoding should use
534   // SetTransferEncodingToChunkedAndClearContentLength() or
535   // SetNoTransferEncoding() instead.
536   void AppendHeader(absl::string_view key, absl::string_view value) override;
537 
538   // Appends ',value' to an existing header named 'key'.  If no header with the
539   // correct key exists, it will call AppendHeader(key, value).  Calling this
540   // function on a key which exists several times in the headers will produce
541   // unpredictable results.
542   void AppendToHeader(absl::string_view key, absl::string_view value) override;
543 
544   // Appends ', value' to an existing header named 'key'.  If no header with the
545   // correct key exists, it will call AppendHeader(key, value).  Calling this
546   // function on a key which exists several times in the headers will produce
547   // unpredictable results.
548   void AppendToHeaderWithCommaAndSpace(absl::string_view key,
549                                        absl::string_view value) override;
550 
551   // Returns the value corresponding to the given header key. Returns an empty
552   // string if the header key does not exist. For headers that may consist of
553   // multiple lines, use GetAllOfHeader() instead.
554   // Make the QuicheLowerCaseString overload visible,
555   // and only override the absl::string_view one.
556   using HeaderApi::GetHeader;
557   absl::string_view GetHeader(absl::string_view key) const override;
558 
559   // Iterates over all currently valid header lines, appending their
560   // values into the vector 'out', in top-to-bottom order.
561   // Header-lines which have been erased are not currently valid, and
562   // will not have their values appended. Empty values will be
563   // represented as empty string. If 'key' doesn't exist in the headers at
564   // all, out will not be changed. We do not clear the vector out
565   // before adding new entries. If there are header lines with matching
566   // key but empty value then they are also added to the vector out.
567   // (Basically empty values are not treated in any special manner).
568   //
569   // Example:
570   // Input header:
571   // "GET / HTTP/1.0\r\n"
572   //    "key1: v1\r\n"
573   //    "key1: \r\n"
574   //    "key1:\r\n"
575   //    "key1:  v1\r\n"
576   //    "key1:v2\r\n"
577   //
578   //  vector out is initially: ["foo"]
579   //  vector out after GetAllOfHeader("key1", &out) is:
580   // ["foo", "v1", "", "", "v1", "v2"]
581   //
582   // See gfe::header_properties::IsMultivaluedHeader() for which headers
583   // GFE treats as being multivalued.
584 
585   // Make the QuicheLowerCaseString overload visible,
586   // and only override the absl::string_view one.
587   using HeaderApi::GetAllOfHeader;
588   void GetAllOfHeader(absl::string_view key,
589                       std::vector<absl::string_view>* out) const override;
590 
591   // Same as above, but iterates over all header lines including removed ones.
592   // Appends their values into the vector 'out' in top-to-bottom order,
593   // first all valid headers then all that were removed.
594   void GetAllOfHeaderIncludeRemoved(absl::string_view key,
595                                     std::vector<absl::string_view>* out) const;
596 
597   // Joins all values for `key` into a comma-separated string.
598   // Make the QuicheLowerCaseString overload visible,
599   // and only override the absl::string_view one.
600   using HeaderApi::GetAllOfHeaderAsString;
601   std::string GetAllOfHeaderAsString(absl::string_view key) const override;
602 
603   // Determine if a given header is present.  Case-insensitive.
HasHeader(absl::string_view key)604   inline bool HasHeader(absl::string_view key) const override {
605     return GetConstHeaderLinesIterator(key) != header_lines_.end();
606   }
607 
608   // Goes through all headers with key 'key' and checks to see if one of the
609   // values is 'value'.  Returns true if there are headers with the desired key
610   // and value, false otherwise.  Case-insensitive for the key; case-sensitive
611   // for the value.
HeaderHasValue(absl::string_view key,absl::string_view value)612   bool HeaderHasValue(absl::string_view key,
613                       absl::string_view value) const override {
614     return HeaderHasValueHelper(key, value, true);
615   }
616   // Same as above, but also case-insensitive for the value.
HeaderHasValueIgnoreCase(absl::string_view key,absl::string_view value)617   bool HeaderHasValueIgnoreCase(absl::string_view key,
618                                 absl::string_view value) const override {
619     return HeaderHasValueHelper(key, value, false);
620   }
621 
622   // Returns true iff any header 'key' exists with non-empty value.
623   bool HasNonEmptyHeader(absl::string_view key) const override;
624 
625   const_header_lines_iterator GetHeaderPosition(absl::string_view key) const;
626 
627   // Removes all headers in given set |keys| at once efficiently. Keys
628   // are case insensitive.
629   //
630   // Alternatives considered:
631   //
632   // 1. Use string_hash_set<>, the caller (such as ClearHopByHopHeaders) lower
633   // cases the keys and RemoveAllOfHeaderInList just does lookup. This according
634   // to microbenchmark gives the best performance because it does not require
635   // an extra copy of the hash table. However, it is not taken because of the
636   // possible risk that caller could forget to lowercase the keys.
637   //
638   // 2. Use flat_hash_set<StringPiece, StringPieceCaseHash,StringPieceCaseEqual>
639   // or string_hash_set<StringPieceCaseHash, StringPieceCaseEqual>. Both appear
640   // to have (much) worse performance with WithoutDupToken and LongHeader case
641   // in microbenchmark.
642   void RemoveAllOfHeaderInList(const HeaderTokenList& keys) override;
643 
644   void RemoveAllOfHeader(absl::string_view key) override;
645 
646   // Removes all headers starting with 'key' [case insensitive]
647   void RemoveAllHeadersWithPrefix(absl::string_view prefix) override;
648 
649   // Returns true if we have at least one header with given prefix
650   // [case insensitive]. Currently for test use only.
651   bool HasHeadersWithPrefix(absl::string_view prefix) const override;
652 
653   // Returns the key value pairs for all headers where the header key begins
654   // with the specified prefix.
655   void GetAllOfHeaderWithPrefix(
656       absl::string_view prefix,
657       std::vector<std::pair<absl::string_view, absl::string_view>>* out)
658       const override;
659 
660   void GetAllHeadersWithLimit(
661       std::vector<std::pair<absl::string_view, absl::string_view>>* out,
662       int limit) const override;
663 
664   // Removes all values equal to a given value from header lines with given key.
665   // All string operations done here are case-sensitive.
666   // If a header line has only values matching the given value, the entire
667   // line is removed.
668   // If the given value is found in a multi-value header line mixed with other
669   // values, the line is edited in-place to remove the values.
670   // Returns the number of occurrences of value that were removed.
671   // This method runs in linear time.
672   size_t RemoveValue(absl::string_view key, absl::string_view value);
673 
674   // Returns the upper bound on the required buffer space to fully write out
675   // the header object (this include the first line, all header lines, and the
676   // final line separator that marks the ending of the header).
677   size_t GetSizeForWriteBuffer() const override;
678 
679   // Indicates if to serialize headers with lower-case header keys.
680   enum class CaseOption { kNoModification, kLowercase, kPropercase };
681 
682   // Indicates if to coalesce headers with multiple values to match Envoy/GFE3.
683   enum class CoalesceOption { kNoCoalesce, kCoalesce };
684 
685   // The following WriteHeader* methods are template member functions that
686   // place one requirement on the Buffer class: it must implement a Write
687   // method that takes a pointer and a length. The buffer passed in is not
688   // required to be stretchable. For non-stretchable buffers, the user must
689   // call GetSizeForWriteBuffer() to find out the upper bound on the output
690   // buffer space required to make sure that the entire header is serialized.
691   // BalsaHeaders will not check that there is adequate space in the buffer
692   // object during the write.
693 
694   // Writes the entire header and the final line separator that marks the end
695   // of the HTTP header section to the buffer. After this method returns, no
696   // more header data should be written to the buffer.
697   template <typename Buffer>
WriteHeaderAndEndingToBuffer(Buffer * buffer,CaseOption case_option,CoalesceOption coalesce_option)698   void WriteHeaderAndEndingToBuffer(Buffer* buffer, CaseOption case_option,
699                                     CoalesceOption coalesce_option) const {
700     WriteToBuffer(buffer, case_option, coalesce_option);
701     WriteHeaderEndingToBuffer(buffer);
702   }
703 
704   template <typename Buffer>
WriteHeaderAndEndingToBuffer(Buffer * buffer)705   void WriteHeaderAndEndingToBuffer(Buffer* buffer) const {
706     WriteHeaderAndEndingToBuffer(buffer, CaseOption::kNoModification,
707                                  CoalesceOption::kNoCoalesce);
708   }
709 
710   // Writes the final line separator to the buffer to terminate the HTTP header
711   // section.  After this method returns, no more header data should be written
712   // to the buffer.
713   template <typename Buffer>
WriteHeaderEndingToBuffer(Buffer * buffer)714   static void WriteHeaderEndingToBuffer(Buffer* buffer) {
715     buffer->WriteString("\r\n");
716   }
717 
718   // Writes the entire header to the buffer without the line separator that
719   // terminates the HTTP header. This lets users append additional header lines
720   // using WriteHeaderLineToBuffer and then terminate the header with
721   // WriteHeaderEndingToBuffer as the header is serialized to the buffer,
722   // without having to first copy the header.
723   template <typename Buffer>
724   void WriteToBuffer(Buffer* buffer, CaseOption case_option,
725                      CoalesceOption coalesce_option) const;
726 
727   template <typename Buffer>
WriteToBuffer(Buffer * buffer)728   void WriteToBuffer(Buffer* buffer) const {
729     WriteToBuffer(buffer, CaseOption::kNoModification,
730                   CoalesceOption::kNoCoalesce);
731   }
732 
733   // Used by WriteToBuffer to coalesce multiple values of headers listed in
734   // |multivalued_headers| into a single comma-separated value. Public for test.
735   template <typename Buffer>
736   void WriteToBufferCoalescingMultivaluedHeaders(
737       Buffer* buffer, const MultivaluedHeadersSet& multivalued_headers,
738       CaseOption case_option) const;
739 
740   // Populates |multivalues| with values of |header_lines_| with keys present
741   // in |multivalued_headers| set.
742   void GetValuesOfMultivaluedHeaders(
743       const MultivaluedHeadersSet& multivalued_headers,
744       MultivaluedHeadersValuesMap* multivalues) const;
745 
ToPropercase(absl::string_view header)746   static std::string ToPropercase(absl::string_view header) {
747     std::string copy = std::string(header);
748     bool should_uppercase = true;
749     for (char& c : copy) {
750       if (!absl::ascii_isalnum(c)) {
751         should_uppercase = true;
752       } else if (should_uppercase) {
753         c = absl::ascii_toupper(c);
754         should_uppercase = false;
755       } else {
756         c = absl::ascii_tolower(c);
757       }
758     }
759     return copy;
760   }
761 
762   template <typename Buffer>
WriteHeaderKeyToBuffer(Buffer * buffer,absl::string_view key,CaseOption case_option)763   void WriteHeaderKeyToBuffer(Buffer* buffer, absl::string_view key,
764                               CaseOption case_option) const {
765     if (case_option == CaseOption::kLowercase) {
766       buffer->WriteString(absl::AsciiStrToLower(key));
767     } else if (case_option == CaseOption::kPropercase) {
768       const auto& header_set = quiche::GetStandardHeaderSet();
769       auto it = header_set.find(key);
770       if (it != header_set.end()) {
771         buffer->WriteString(*it);
772       } else {
773         buffer->WriteString(ToPropercase(key));
774       }
775     } else {
776       buffer->WriteString(key);
777     }
778   }
779 
780   // Takes a header line in the form of a key/value pair and append it to the
781   // buffer. This function should be called after WriteToBuffer to
782   // append additional header lines to the header without copying the header.
783   // When the user is done with appending to the buffer,
784   // WriteHeaderEndingToBuffer must be used to terminate the HTTP
785   // header in the buffer. This method is a no-op if key is empty.
786   template <typename Buffer>
WriteHeaderLineToBuffer(Buffer * buffer,absl::string_view key,absl::string_view value,CaseOption case_option)787   void WriteHeaderLineToBuffer(Buffer* buffer, absl::string_view key,
788                                absl::string_view value,
789                                CaseOption case_option) const {
790     // If the key is empty, we don't want to write the rest because it
791     // will not be a well-formed header line.
792     if (!key.empty()) {
793       WriteHeaderKeyToBuffer(buffer, key, case_option);
794       buffer->WriteString(": ");
795       buffer->WriteString(value);
796       buffer->WriteString("\r\n");
797     }
798   }
799 
800   // Takes a header line in the form of a key and vector of values and appends
801   // it to the buffer. This function should be called after WriteToBuffer to
802   // append additional header lines to the header without copying the header.
803   // When the user is done with appending to the buffer,
804   // WriteHeaderEndingToBuffer must be used to terminate the HTTP
805   // header in the buffer. This method is a no-op if the |key| is empty.
806   template <typename Buffer>
WriteHeaderLineValuesToBuffer(Buffer * buffer,absl::string_view key,const std::vector<absl::string_view> & values,CaseOption case_option)807   void WriteHeaderLineValuesToBuffer(
808       Buffer* buffer, absl::string_view key,
809       const std::vector<absl::string_view>& values,
810       CaseOption case_option) const {
811     // If the key is empty, we don't want to write the rest because it
812     // will not be a well-formed header line.
813     if (!key.empty()) {
814       WriteHeaderKeyToBuffer(buffer, key, case_option);
815       buffer->WriteString(": ");
816       for (auto it = values.begin();;) {
817         buffer->WriteString(*it);
818         if (++it == values.end()) {
819           break;
820         }
821         buffer->WriteString(",");
822       }
823       buffer->WriteString("\r\n");
824     }
825   }
826 
827   // Dump the textural representation of the header object to a string, which
828   // is suitable for writing out to logs. All CRLF will be printed out as \n.
829   // This function can be called on a header object in any state. Raw header
830   // data will be printed out if the header object is not completely parsed,
831   // e.g., when there was an error in the middle of parsing.
832   // The header content is appended to the string; the original content is not
833   // cleared.
834   // If used in test cases, WillNotWriteFromFramer() may be of interest.
835   void DumpToString(std::string* str) const;
836   std::string DebugString() const override;
837 
838   bool ForEachHeader(
839       quiche::UnretainedCallback<bool(const absl::string_view key,
840                                       const absl::string_view value)>
841           fn) const override;
842 
843   void DumpToPrefixedString(const char* spaces, std::string* str) const;
844 
first_line()845   absl::string_view first_line() const {
846     QUICHE_DCHECK_GE(whitespace_4_idx_, non_whitespace_1_idx_);
847     return whitespace_4_idx_ == non_whitespace_1_idx_
848                ? ""
849                : absl::string_view(
850                      BeginningOfFirstLine() + non_whitespace_1_idx_,
851                      whitespace_4_idx_ - non_whitespace_1_idx_);
852   }
first_line_of_request()853   std::string first_line_of_request() const override {
854     return std::string(first_line());
855   }
856 
857   // Returns the parsed value of the response code if it has been parsed.
858   // Guaranteed to return 0 when unparsed (though it is a much better idea to
859   // verify that the BalsaFrame had no errors while parsing).
860   // This may return response codes which are outside the normal bounds of
861   // HTTP response codes-- it is up to the user of this class to ensure that
862   // the response code is one which is interpretable.
parsed_response_code()863   size_t parsed_response_code() const override { return parsed_response_code_; }
864 
request_method()865   absl::string_view request_method() const override {
866     QUICHE_DCHECK_GE(whitespace_2_idx_, non_whitespace_1_idx_);
867     return whitespace_2_idx_ == non_whitespace_1_idx_
868                ? ""
869                : absl::string_view(
870                      BeginningOfFirstLine() + non_whitespace_1_idx_,
871                      whitespace_2_idx_ - non_whitespace_1_idx_);
872   }
873 
response_version()874   absl::string_view response_version() const override {
875     // Note: There is no difference between request_method() and
876     // response_version(). They both could be called
877     // GetFirstTokenFromFirstline()... but that wouldn't be anywhere near as
878     // descriptive.
879     return request_method();
880   }
881 
request_uri()882   absl::string_view request_uri() const override {
883     QUICHE_DCHECK_GE(whitespace_3_idx_, non_whitespace_2_idx_);
884     return whitespace_3_idx_ == non_whitespace_2_idx_
885                ? ""
886                : absl::string_view(
887                      BeginningOfFirstLine() + non_whitespace_2_idx_,
888                      whitespace_3_idx_ - non_whitespace_2_idx_);
889   }
890 
response_code()891   absl::string_view response_code() const override {
892     // Note: There is no difference between request_uri() and response_code().
893     // They both could be called GetSecondtTokenFromFirstline(), but, as noted
894     // in an earlier comment, that wouldn't be as descriptive.
895     return request_uri();
896   }
897 
request_version()898   absl::string_view request_version() const override {
899     QUICHE_DCHECK_GE(whitespace_4_idx_, non_whitespace_3_idx_);
900     return whitespace_4_idx_ == non_whitespace_3_idx_
901                ? ""
902                : absl::string_view(
903                      BeginningOfFirstLine() + non_whitespace_3_idx_,
904                      whitespace_4_idx_ - non_whitespace_3_idx_);
905   }
906 
response_reason_phrase()907   absl::string_view response_reason_phrase() const override {
908     // Note: There is no difference between request_version() and
909     // response_reason_phrase(). They both could be called
910     // GetThirdTokenFromFirstline(), but, as noted in an earlier comment, that
911     // wouldn't be as descriptive.
912     return request_version();
913   }
914 
SetRequestFirstlineFromStringPieces(absl::string_view method,absl::string_view uri,absl::string_view version)915   void SetRequestFirstlineFromStringPieces(absl::string_view method,
916                                            absl::string_view uri,
917                                            absl::string_view version) {
918     SetFirstlineFromStringPieces(method, uri, version);
919   }
920 
921   void SetResponseFirstline(absl::string_view version,
922                             size_t parsed_response_code,
923                             absl::string_view reason_phrase);
924 
925   // These functions are exactly the same, except that their names are
926   // different. This is done so that the code using this class is more
927   // expressive.
928   void SetRequestMethod(absl::string_view method) override;
929   void SetResponseVersion(absl::string_view version) override;
930 
931   void SetRequestUri(absl::string_view uri) override;
932   void SetResponseCode(absl::string_view code) override;
set_parsed_response_code(size_t parsed_response_code)933   void set_parsed_response_code(size_t parsed_response_code) {
934     parsed_response_code_ = parsed_response_code;
935   }
936   void SetParsedResponseCodeAndUpdateFirstline(
937       size_t parsed_response_code) override;
938 
939   // These functions are exactly the same, except that their names are
940   // different. This is done so that the code using this class is more
941   // expressive.
942   void SetRequestVersion(absl::string_view version) override;
943   void SetResponseReasonPhrase(absl::string_view reason_phrase) override;
944 
945   // Simple accessors to some of the internal state
transfer_encoding_is_chunked()946   bool transfer_encoding_is_chunked() const {
947     return transfer_encoding_is_chunked_;
948   }
949 
ResponseCodeImpliesNoBody(size_t code)950   static bool ResponseCodeImpliesNoBody(size_t code) {
951     // From HTTP spec section 6.1.1 all 1xx responses must not have a body,
952     // as well as 204 No Content and 304 Not Modified.
953     return ((code >= 100) && (code <= 199)) || (code == 204) || (code == 304);
954   }
955 
956   // Note: never check this for requests. Nothing bad will happen if you do,
957   // but spec does not allow requests framed by connection close.
958   // TODO(vitaliyl): refactor.
is_framed_by_connection_close()959   bool is_framed_by_connection_close() const {
960     // We declare that response is framed by connection close if it has no
961     // content-length, no transfer encoding, and is allowed to have a body by
962     // the HTTP spec.
963     // parsed_response_code_ is 0 for requests, so ResponseCodeImpliesNoBody
964     // will return false.
965     return (content_length_status_ == BalsaHeadersEnums::NO_CONTENT_LENGTH) &&
966            !transfer_encoding_is_chunked_ &&
967            !ResponseCodeImpliesNoBody(parsed_response_code_);
968   }
969 
content_length()970   size_t content_length() const override { return content_length_; }
content_length_status()971   BalsaHeadersEnums::ContentLengthStatus content_length_status() const {
972     return content_length_status_;
973   }
content_length_valid()974   bool content_length_valid() const override {
975     return content_length_status_ == BalsaHeadersEnums::VALID_CONTENT_LENGTH;
976   }
977 
978   // SetContentLength, SetTransferEncodingToChunkedAndClearContentLength, and
979   // SetNoTransferEncoding modifies the header object to use
980   // content-length and transfer-encoding headers in a consistent
981   // manner. They set all internal flags and status so client can get
982   // a consistent view from various accessors.
983   void SetContentLength(size_t length) override;
984   // Sets transfer-encoding to chunked and updates internal state.
985   void SetTransferEncodingToChunkedAndClearContentLength() override;
986   // Removes transfer-encoding headers and updates internal state.
987   void SetNoTransferEncoding() override;
988 
989   // If you have a response that needs framing by connection close, use this
990   // method instead of RemoveAllOfHeader("Content-Length"). Has no effect if
991   // transfer_encoding_is_chunked().
992   void ClearContentLength();
993 
994   // This should be called if balsa headers are created entirely manually (not
995   // by any of the framer classes) to make sure that function calls like
996   // DumpToString will work correctly.
WillNotWriteFromFramer()997   void WillNotWriteFromFramer() {
998     balsa_buffer_.NoMoreWriteToContiguousBuffer();
999   }
1000 
1001   // True if DoneWritingFromFramer or WillNotWriteFromFramer is called.
FramerIsDoneWriting()1002   bool FramerIsDoneWriting() const {
1003     return !balsa_buffer_.can_write_to_contiguous_buffer();
1004   }
1005 
1006   bool IsEmpty() const override;
1007 
1008   // From HeaderApi and ConstHeaderApi.
1009   absl::string_view Authority() const override;
1010   void ReplaceOrAppendAuthority(absl::string_view value) override;
1011   void RemoveAuthority() override;
1012   void ApplyToCookie(quiche::UnretainedCallback<void(absl::string_view cookie)>
1013                          f) const override;
1014 
set_enforce_header_policy(bool enforce)1015   void set_enforce_header_policy(bool enforce) override {
1016     enforce_header_policy_ = enforce;
1017   }
1018 
1019   // Removes the last token from the header value. In the presence of multiple
1020   // header lines with given key, will remove the last token of the last line.
1021   // Can be useful if the last encoding has to be removed.
1022   void RemoveLastTokenFromHeaderValue(absl::string_view key);
1023 
1024   // Gets the list of names of headers that are multivalued in Envoy.
1025   static const MultivaluedHeadersSet& multivalued_envoy_headers();
1026 
1027   // Returns true if HTTP responses with this response code have bodies.
1028   static bool ResponseCanHaveBody(int response_code);
1029 
1030   // Given a pointer to the beginning and the end of the header value
1031   // in some buffer, populates tokens list with beginning and end indices
1032   // of all tokens present in the value string.
1033   static void ParseTokenList(absl::string_view header_value,
1034                              HeaderTokenList* tokens);
1035 
1036  private:
1037   typedef std::vector<HeaderLineDescription> HeaderLines;
1038 
1039   class iterator_base;
1040 
1041   friend class BalsaFrame;
1042   friend class gfe2::Http2HeaderValidator;
1043   friend class SpdyPayloadFramer;
1044   friend class HTTPMessage;
1045   friend class test::BalsaHeadersTestPeer;
1046 
1047   friend bool ParseHTTPFirstLine(const char* begin, const char* end,
1048                                  bool is_request, BalsaHeaders* headers,
1049                                  BalsaFrameEnums::ErrorCode* error_code);
1050 
1051   // Reverse iterators have been removed for lack of use, refer to
1052   // cl/30618773 in case they are needed.
1053 
BeginningOfFirstLine()1054   const char* BeginningOfFirstLine() const {
1055     return GetPtr(firstline_buffer_base_idx_);
1056   }
1057 
BeginningOfFirstLine()1058   char* BeginningOfFirstLine() { return GetPtr(firstline_buffer_base_idx_); }
1059 
GetPtr(BalsaBuffer::Blocks::size_type block_idx)1060   char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) {
1061     return balsa_buffer_.GetPtr(block_idx);
1062   }
1063 
GetPtr(BalsaBuffer::Blocks::size_type block_idx)1064   const char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) const {
1065     return balsa_buffer_.GetPtr(block_idx);
1066   }
1067 
WriteFromFramer(const char * ptr,size_t size)1068   void WriteFromFramer(const char* ptr, size_t size) {
1069     balsa_buffer_.WriteToContiguousBuffer(absl::string_view(ptr, size));
1070   }
1071 
DoneWritingFromFramer()1072   void DoneWritingFromFramer() {
1073     balsa_buffer_.NoMoreWriteToContiguousBuffer();
1074   }
1075 
OriginalHeaderStreamBegin()1076   const char* OriginalHeaderStreamBegin() const {
1077     return balsa_buffer_.StartOfFirstBlock();
1078   }
1079 
OriginalHeaderStreamEnd()1080   const char* OriginalHeaderStreamEnd() const {
1081     return balsa_buffer_.EndOfFirstBlock();
1082   }
1083 
GetReadableBytesFromHeaderStream()1084   size_t GetReadableBytesFromHeaderStream() const {
1085     return balsa_buffer_.GetReadableBytesOfFirstBlock();
1086   }
1087 
GetReadablePtrFromHeaderStream()1088   absl::string_view GetReadablePtrFromHeaderStream() {
1089     return {OriginalHeaderStreamBegin(), GetReadableBytesFromHeaderStream()};
1090   }
1091 
1092   absl::string_view GetValueFromHeaderLineDescription(
1093       const HeaderLineDescription& line) const;
1094 
1095   void AddAndMakeDescription(absl::string_view key, absl::string_view value,
1096                              HeaderLineDescription* d);
1097 
1098   void AppendAndMakeDescription(absl::string_view key, absl::string_view value,
1099                                 HeaderLineDescription* d);
1100 
1101   // Removes all header lines with the given key starting at start.
1102   void RemoveAllOfHeaderStartingAt(absl::string_view key,
1103                                    HeaderLines::iterator start);
1104 
1105   HeaderLines::const_iterator GetConstHeaderLinesIterator(
1106       absl::string_view key) const;
1107 
1108   HeaderLines::iterator GetHeaderLinesIterator(absl::string_view key,
1109                                                HeaderLines::iterator start);
1110 
1111   HeaderLines::iterator GetHeaderLinesIteratorForLastMultivaluedHeader(
1112       absl::string_view key);
1113 
1114   template <typename IteratorType>
1115   const IteratorType HeaderLinesBeginHelper() const;
1116 
1117   template <typename IteratorType>
1118   const IteratorType HeaderLinesEndHelper() const;
1119 
1120   // Helper function for HeaderHasValue and HeaderHasValueIgnoreCase that
1121   // does most of the work.
1122   bool HeaderHasValueHelper(absl::string_view key, absl::string_view value,
1123                             bool case_sensitive) const;
1124 
1125   // Called by header removal methods to reset internal values for transfer
1126   // encoding or content length if we're removing the corresponding headers.
1127   void MaybeClearSpecialHeaderValues(absl::string_view key);
1128 
1129   void SetFirstlineFromStringPieces(absl::string_view firstline_a,
1130                                     absl::string_view firstline_b,
1131                                     absl::string_view firstline_c);
1132   BalsaBuffer balsa_buffer_;
1133 
1134   size_t content_length_;
1135   BalsaHeadersEnums::ContentLengthStatus content_length_status_;
1136   size_t parsed_response_code_;
1137   // HTTP firstlines all have the following structure:
1138   //  LWS         NONWS  LWS    NONWS   LWS    NONWS   NOTCRLF  CRLF
1139   //  [\t \r\n]+ [^\t ]+ [\t ]+ [^\t ]+ [\t ]+ [^\t ]+ [^\r\n]+ "\r\n"
1140   //  ws1        nws1    ws2    nws2    ws3    nws3             ws4
1141   //  |          [-------)      [-------)      [----------------)
1142   //    REQ:     method         request_uri    version
1143   //   RESP:     version        statuscode     reason
1144   //
1145   //   The first NONWS->LWS component we'll call firstline_a.
1146   //   The second firstline_b, and the third firstline_c.
1147   //
1148   //   firstline_a goes from nws1 to (but not including) ws2
1149   //   firstline_b goes from nws2 to (but not including) ws3
1150   //   firstline_c goes from nws3 to (but not including) ws4
1151   //
1152   // In the code:
1153   //    ws1 == whitespace_1_idx_
1154   //   nws1 == non_whitespace_1_idx_
1155   //    ws2 == whitespace_2_idx_
1156   //   nws2 == non_whitespace_2_idx_
1157   //    ws3 == whitespace_3_idx_
1158   //   nws3 == non_whitespace_3_idx_
1159   //    ws4 == whitespace_4_idx_
1160   BalsaBuffer::Blocks::size_type firstline_buffer_base_idx_;
1161   size_t whitespace_1_idx_;
1162   size_t non_whitespace_1_idx_;
1163   size_t whitespace_2_idx_;
1164   size_t non_whitespace_2_idx_;
1165   size_t whitespace_3_idx_;
1166   size_t non_whitespace_3_idx_;
1167   size_t whitespace_4_idx_;
1168 
1169   bool transfer_encoding_is_chunked_;
1170 
1171   // If true, QUICHE_BUG if a header that starts with an invalid prefix is
1172   // explicitly set.
1173   bool enforce_header_policy_ = true;
1174 
1175   HeaderLines header_lines_;
1176 };
1177 
1178 // Base class for iterating the headers in a BalsaHeaders object, returning a
1179 // pair of string_view's for each header.
1180 class QUICHE_EXPORT BalsaHeaders::iterator_base
1181     : public std::iterator<std::forward_iterator_tag,
1182                            std::pair<absl::string_view, absl::string_view>> {
1183  public:
iterator_base()1184   iterator_base() : headers_(nullptr), idx_(0) {}
1185 
1186   std::pair<absl::string_view, absl::string_view>& operator*() const {
1187     return Lookup(idx_);
1188   }
1189 
1190   std::pair<absl::string_view, absl::string_view>* operator->() const {
1191     return &(this->operator*());
1192   }
1193 
1194   bool operator==(const BalsaHeaders::iterator_base& it) const {
1195     return idx_ == it.idx_;
1196   }
1197 
1198   bool operator<(const BalsaHeaders::iterator_base& it) const {
1199     return idx_ < it.idx_;
1200   }
1201 
1202   bool operator<=(const BalsaHeaders::iterator_base& it) const {
1203     return idx_ <= it.idx_;
1204   }
1205 
1206   bool operator!=(const BalsaHeaders::iterator_base& it) const {
1207     return !(*this == it);
1208   }
1209 
1210   bool operator>(const BalsaHeaders::iterator_base& it) const {
1211     return it < *this;
1212   }
1213 
1214   bool operator>=(const BalsaHeaders::iterator_base& it) const {
1215     return it <= *this;
1216   }
1217 
1218   // This mainly exists so that we can have interesting output for
1219   // unittesting. The EXPECT_EQ, EXPECT_NE functions require that
1220   // operator<< work for the classes it sees.  It would be better if there
1221   // was an additional traits-like system for the gUnit output... but oh
1222   // well.
1223   friend QUICHE_EXPORT std::ostream& operator<<(std::ostream& os,
1224                                                 const iterator_base& it) {
1225     os << "[" << it.headers_ << ", " << it.idx_ << "]";
1226     return os;
1227   }
1228 
1229  private:
1230   friend class BalsaHeaders;
1231 
iterator_base(const BalsaHeaders * headers,HeaderLines::size_type index)1232   iterator_base(const BalsaHeaders* headers, HeaderLines::size_type index)
1233       : headers_(headers), idx_(index) {}
1234 
increment()1235   void increment() {
1236     value_.reset();
1237     const HeaderLines& header_lines = headers_->header_lines_;
1238     const HeaderLines::size_type header_lines_size = header_lines.size();
1239     const HeaderLines::size_type original_idx = idx_;
1240     do {
1241       ++idx_;
1242     } while (idx_ < header_lines_size && header_lines[idx_].skip == true);
1243     // The condition below exists so that ++(end() - 1) == end(), even
1244     // if there are only 'skip == true' elements between the end() iterator
1245     // and the end of the vector of HeaderLineDescriptions.
1246     if (idx_ == header_lines_size) {
1247       idx_ = original_idx + 1;
1248     }
1249   }
1250 
Lookup(HeaderLines::size_type index)1251   std::pair<absl::string_view, absl::string_view>& Lookup(
1252       HeaderLines::size_type index) const {
1253     QUICHE_DCHECK_LT(index, headers_->header_lines_.size());
1254     if (!value_.has_value()) {
1255       const HeaderLineDescription& line = headers_->header_lines_[index];
1256       const char* stream_begin = headers_->GetPtr(line.buffer_base_idx);
1257       value_ =
1258           std::make_pair(absl::string_view(stream_begin + line.first_char_idx,
1259                                            line.KeyLength()),
1260                          absl::string_view(stream_begin + line.value_begin_idx,
1261                                            line.ValuesLength()));
1262     }
1263     return *value_;
1264   }
1265 
1266   const BalsaHeaders* headers_;
1267   HeaderLines::size_type idx_;
1268   mutable std::optional<std::pair<absl::string_view, absl::string_view>> value_;
1269 };
1270 
1271 // A const iterator for all the header lines.
1272 class QUICHE_EXPORT BalsaHeaders::const_header_lines_iterator
1273     : public BalsaHeaders::iterator_base {
1274  public:
const_header_lines_iterator()1275   const_header_lines_iterator() : iterator_base() {}
1276 
1277   const_header_lines_iterator& operator++() {
1278     iterator_base::increment();
1279     return *this;
1280   }
1281 
1282  private:
1283   friend class BalsaHeaders;
1284 
const_header_lines_iterator(const BalsaHeaders * headers,HeaderLines::size_type index)1285   const_header_lines_iterator(const BalsaHeaders* headers,
1286                               HeaderLines::size_type index)
1287       : iterator_base(headers, index) {}
1288 };
1289 
1290 // A const iterator that stops only on header lines for a particular key.
1291 class QUICHE_EXPORT BalsaHeaders::const_header_lines_key_iterator
1292     : public BalsaHeaders::iterator_base {
1293  public:
1294   const_header_lines_key_iterator& operator++() {
1295     do {
1296       iterator_base::increment();
1297     } while (!AtEnd() && !absl::EqualsIgnoreCase(key_, (**this).first));
1298     return *this;
1299   }
1300 
1301   // Only forward-iteration makes sense, so no operator-- defined.
1302 
1303  private:
1304   friend class BalsaHeaders;
1305 
const_header_lines_key_iterator(const BalsaHeaders * headers,HeaderLines::size_type index,absl::string_view key)1306   const_header_lines_key_iterator(const BalsaHeaders* headers,
1307                                   HeaderLines::size_type index,
1308                                   absl::string_view key)
1309       : iterator_base(headers, index), key_(key) {}
1310 
1311   // Should only be used for creating an end iterator.
const_header_lines_key_iterator(const BalsaHeaders * headers,HeaderLines::size_type index)1312   const_header_lines_key_iterator(const BalsaHeaders* headers,
1313                                   HeaderLines::size_type index)
1314       : iterator_base(headers, index) {}
1315 
AtEnd()1316   bool AtEnd() const { return *this >= headers_->lines().end(); }
1317 
1318   absl::string_view key_;
1319 };
1320 
1321 inline BalsaHeaders::iterator_range<BalsaHeaders::const_header_lines_iterator>
lines()1322 BalsaHeaders::lines() const {
1323   return {HeaderLinesBeginHelper<const_header_lines_iterator>(),
1324           HeaderLinesEndHelper<const_header_lines_iterator>()};
1325 }
1326 
1327 inline BalsaHeaders::iterator_range<
1328     BalsaHeaders::const_header_lines_key_iterator>
lines(absl::string_view key)1329 BalsaHeaders::lines(absl::string_view key) const {
1330   return {GetIteratorForKey(key), header_lines_key_end()};
1331 }
1332 
1333 inline BalsaHeaders::const_header_lines_key_iterator
header_lines_key_end()1334 BalsaHeaders::header_lines_key_end() const {
1335   return HeaderLinesEndHelper<const_header_lines_key_iterator>();
1336 }
1337 
erase(const const_header_lines_iterator & it)1338 inline void BalsaHeaders::erase(const const_header_lines_iterator& it) {
1339   QUICHE_DCHECK_EQ(it.headers_, this);
1340   QUICHE_DCHECK_LT(it.idx_, header_lines_.size());
1341   header_lines_[it.idx_].skip = true;
1342 }
1343 
1344 template <typename Buffer>
WriteToBuffer(Buffer * buffer,CaseOption case_option,CoalesceOption coalesce_option)1345 void BalsaHeaders::WriteToBuffer(Buffer* buffer, CaseOption case_option,
1346                                  CoalesceOption coalesce_option) const {
1347   // write the first line.
1348   const absl::string_view firstline = first_line();
1349   if (!firstline.empty()) {
1350     buffer->WriteString(firstline);
1351   }
1352   buffer->WriteString("\r\n");
1353   if (coalesce_option != CoalesceOption::kCoalesce) {
1354     const HeaderLines::size_type end = header_lines_.size();
1355     for (HeaderLines::size_type i = 0; i < end; ++i) {
1356       const HeaderLineDescription& line = header_lines_[i];
1357       if (line.skip) {
1358         continue;
1359       }
1360       const char* line_ptr = GetPtr(line.buffer_base_idx);
1361       WriteHeaderLineToBuffer(
1362           buffer,
1363           absl::string_view(line_ptr + line.first_char_idx, line.KeyLength()),
1364           absl::string_view(line_ptr + line.value_begin_idx,
1365                             line.ValuesLength()),
1366           case_option);
1367     }
1368   } else {
1369     WriteToBufferCoalescingMultivaluedHeaders(
1370         buffer, multivalued_envoy_headers(), case_option);
1371   }
1372 }
1373 
GetValuesOfMultivaluedHeaders(const MultivaluedHeadersSet & multivalued_headers,MultivaluedHeadersValuesMap * multivalues)1374 inline void BalsaHeaders::GetValuesOfMultivaluedHeaders(
1375     const MultivaluedHeadersSet& multivalued_headers,
1376     MultivaluedHeadersValuesMap* multivalues) const {
1377   multivalues->reserve(header_lines_.capacity());
1378 
1379   // Find lines that need to be coalesced and store them in |multivalues|.
1380   for (const auto& line : header_lines_) {
1381     if (line.skip) {
1382       continue;
1383     }
1384     const char* line_ptr = GetPtr(line.buffer_base_idx);
1385     absl::string_view header_key =
1386         absl::string_view(line_ptr + line.first_char_idx, line.KeyLength());
1387     // If this is multivalued header, it may need to be coalesced.
1388     if (multivalued_headers.contains(header_key)) {
1389       absl::string_view header_value = absl::string_view(
1390           line_ptr + line.value_begin_idx, line.ValuesLength());
1391       // Add |header_value| to the vector of values for this |header_key|,
1392       // therefore preserving the order of values for the same key.
1393       (*multivalues)[header_key].push_back(header_value);
1394     }
1395   }
1396 }
1397 
1398 template <typename Buffer>
WriteToBufferCoalescingMultivaluedHeaders(Buffer * buffer,const MultivaluedHeadersSet & multivalued_headers,CaseOption case_option)1399 void BalsaHeaders::WriteToBufferCoalescingMultivaluedHeaders(
1400     Buffer* buffer, const MultivaluedHeadersSet& multivalued_headers,
1401     CaseOption case_option) const {
1402   MultivaluedHeadersValuesMap multivalues;
1403   GetValuesOfMultivaluedHeaders(multivalued_headers, &multivalues);
1404 
1405   // Write out header lines while coalescing those that need to be coalesced.
1406   for (const auto& line : header_lines_) {
1407     if (line.skip) {
1408       continue;
1409     }
1410     const char* line_ptr = GetPtr(line.buffer_base_idx);
1411     absl::string_view header_key =
1412         absl::string_view(line_ptr + line.first_char_idx, line.KeyLength());
1413     auto header_multivalue = multivalues.find(header_key);
1414     // If current line doesn't need to be coalesced (as it is either not
1415     // multivalue, or has just a single value so it equals to current line),
1416     // then just write it out.
1417     if (header_multivalue == multivalues.end() ||
1418         header_multivalue->second.size() == 1) {
1419       WriteHeaderLineToBuffer(buffer, header_key,
1420                               absl::string_view(line_ptr + line.value_begin_idx,
1421                                                 line.ValuesLength()),
1422                               case_option);
1423     } else {
1424       // If this line needs to be coalesced, then write all its values and clear
1425       // them, so the subsequent same header keys will not be written.
1426       if (!header_multivalue->second.empty()) {
1427         WriteHeaderLineValuesToBuffer(buffer, header_key,
1428                                       header_multivalue->second, case_option);
1429         // Clear the multivalue list as it is already written out, so subsequent
1430         // same header keys will not be written.
1431         header_multivalue->second.clear();
1432       }
1433     }
1434   }
1435 }
1436 
1437 template <typename IteratorType>
HeaderLinesBeginHelper()1438 const IteratorType BalsaHeaders::HeaderLinesBeginHelper() const {
1439   if (header_lines_.empty()) {
1440     return IteratorType(this, 0);
1441   }
1442   const HeaderLines::size_type header_lines_size = header_lines_.size();
1443   for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) {
1444     if (header_lines_[i].skip == false) {
1445       return IteratorType(this, i);
1446     }
1447   }
1448   return IteratorType(this, 0);
1449 }
1450 
1451 template <typename IteratorType>
HeaderLinesEndHelper()1452 const IteratorType BalsaHeaders::HeaderLinesEndHelper() const {
1453   if (header_lines_.empty()) {
1454     return IteratorType(this, 0);
1455   }
1456   const HeaderLines::size_type header_lines_size = header_lines_.size();
1457   HeaderLines::size_type i = header_lines_size;
1458   do {
1459     --i;
1460     if (header_lines_[i].skip == false) {
1461       return IteratorType(this, i + 1);
1462     }
1463   } while (i != 0);
1464   return IteratorType(this, 0);
1465 }
1466 
1467 }  // namespace quiche
1468 
1469 #endif  // QUICHE_BALSA_BALSA_HEADERS_H_
1470