• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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 #ifndef NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_H_
6 #define NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_H_
7 
8 #include <algorithm>
9 #include <iostream>
10 #include <iterator>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include "base/port.h"
16 #include "base/logging.h"
17 #include "base/string_piece.h"
18 #include "net/tools/flip_server/balsa_enums.h"
19 #include "net/tools/flip_server/string_piece_utils.h"
20 
21 namespace net {
22 
23 // WARNING:
24 // Note that -no- char* returned by any function in this
25 // file is null-terminated.
26 
27 // This class exists to service the specific needs of BalsaHeaders.
28 //
29 // Functional goals:
30 //   1) provide a backing-store for all of the StringPieces that BalsaHeaders
31 //      returns. Every StringPiece returned from BalsaHeaders should remain
32 //      valid until the BalsaHeader's object is cleared, or the header-line is
33 //      erased.
34 //   2) provide a backing-store for BalsaFrame, which requires contiguous memory
35 //      for its fast-path parsing functions. Note that the cost of copying is
36 //      less than the cost of requiring the parser to do slow-path parsing, as
37 //      it would have to check for bounds every byte, instead of every 16 bytes.
38 //
39 // This class is optimized for the case where headers are stored in one of two
40 // buffers. It doesn't make a lot of effort to densely pack memory-- in fact,
41 // it -may- be somewhat memory inefficient. This possible inefficiency allows a
42 // certain simplicity of implementation and speed which makes it worthwhile.
43 // If, in the future, better memory density is required, it should be possible
44 // to reuse the abstraction presented by this object to achieve those goals.
45 //
46 // In the most common use-case, this memory inefficiency should be relatively
47 // small.
48 //
49 // Alternate implementations of BalsaBuffer may include:
50 //  - vector of strings, one per header line (similar to HTTPHeaders)
51 //  - densely packed strings:
52 //    - keep a sorted array/map of free-space linked lists or numbers.
53 //      - use the entry that most closely first your needs.
54 //    - at this point, perhaps just use a vector of strings, and let
55 //      the allocator do the right thing.
56 //
57 class BalsaBuffer {
58  public:
59   static const size_t kDefaultBlocksize = 4096;
60   // We have two friends here. These exist as friends as we
61   // want to allow access to the constructors for the test
62   // class and the Balsa* classes. We put this into the
63   // header file as we want this class to be inlined into the
64   // BalsaHeaders implementation, yet be testable.
65   friend class BalsaBufferTestSpouse;
66   friend class BalsaHeaders;
67 
68   // The BufferBlock is a structure used internally by the
69   // BalsaBuffer class to store the base buffer pointers to
70   // each block, as well as the important metadata for buffer
71   // sizes and bytes free.
72   struct BufferBlock {
73    public:
74     char* buffer;
75     size_t buffer_size;
76     size_t bytes_free;
77 
bytes_usedBufferBlock78     size_t bytes_used() const {
79       return buffer_size - bytes_free;
80     }
start_of_unused_bytesBufferBlock81     char* start_of_unused_bytes() const {
82       return buffer + bytes_used();
83     }
84 
BufferBlockBufferBlock85     BufferBlock() : buffer(NULL), buffer_size(0), bytes_free(0) {}
~BufferBlockBufferBlock86     ~BufferBlock() {}
87 
BufferBlockBufferBlock88     BufferBlock(char* buf, size_t size, size_t free) :
89         buffer(buf), buffer_size(size), bytes_free(free) {}
90     // Yes we want this to be copyable (it gets stuck into vectors).
91     // For this reason, we don't use scoped ptrs, etc. here-- it
92     // is more efficient to manage this memory externally to this
93     // object.
94   };
95 
96   typedef std::vector<BufferBlock> Blocks;
97 
~BalsaBuffer()98   ~BalsaBuffer() {
99     CleanupBlocksStartingFrom(0);
100   }
101 
102   // Returns the total amount of memory used by the buffer blocks.
GetTotalBufferBlockSize()103   size_t GetTotalBufferBlockSize() const {
104     size_t buffer_size = 0;
105     for (Blocks::const_iterator iter = blocks_.begin();
106          iter != blocks_.end();
107          ++iter) {
108       buffer_size += iter->buffer_size;
109     }
110     return buffer_size;
111   }
112 
GetPtr(Blocks::size_type block_idx)113   const char* GetPtr(Blocks::size_type block_idx) const {
114     DCHECK_LT(block_idx, blocks_.size())
115       << block_idx << ", " << blocks_.size();
116     return blocks_[block_idx].buffer;
117   }
118 
GetPtr(Blocks::size_type block_idx)119   char* GetPtr(Blocks::size_type block_idx) {
120     DCHECK_LT(block_idx, blocks_.size())
121       << block_idx << ", " << blocks_.size();
122     return blocks_[block_idx].buffer;
123   }
124 
125   // This function is different from Write(), as it ensures that the data
126   // stored via subsequent calls to this function are all contiguous (and in
127   // the order in which these writes happened). This is essentially the same
128   // as a string append.
129   //
130   // You may call this function at any time between object
131   // construction/Clear(), and the calling of the
132   // NoMoreWriteToContiguousBuffer() function.
133   //
134   // You must not call this function after the NoMoreWriteToContiguousBuffer()
135   // function is called, unless a Clear() has been called since.
136   // If you do, the program will abort().
137   //
138   // This condition is placed upon this code so that calls to Write() can
139   // append to the buffer in the first block safely, and without invaliding
140   // the StringPiece which it returns.
141   //
142   // This function's main intended user is the BalsaFrame class, which,
143   // for reasons of efficiency, requires that the buffer from which it parses
144   // the headers be contiguous.
145   //
WriteToContiguousBuffer(const base::StringPiece & sp)146   void WriteToContiguousBuffer(const base::StringPiece& sp) {
147     if (sp.empty()) {
148       return;
149     }
150     CHECK(can_write_to_contiguous_buffer_);
151     DCHECK_GE(blocks_.size(), 1u);
152     if (blocks_[0].buffer == NULL && sp.size() <= blocksize_) {
153       blocks_[0] = AllocBlock();
154       memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
155     } else if (blocks_[0].bytes_free < sp.size()) {
156       // the first block isn't big enough, resize it.
157       const size_t old_storage_size_used = blocks_[0].bytes_used();
158       const size_t new_storage_size = old_storage_size_used + sp.size();
159       char* new_storage = new char[new_storage_size];
160       char* old_storage = blocks_[0].buffer;
161       if (old_storage_size_used) {
162         memcpy(new_storage, old_storage, old_storage_size_used);
163       }
164       memcpy(new_storage + old_storage_size_used, sp.data(), sp.size());
165       blocks_[0].buffer = new_storage;
166       blocks_[0].bytes_free = sp.size();
167       blocks_[0].buffer_size = new_storage_size;
168       delete[] old_storage;
169     } else {
170       memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
171     }
172     blocks_[0].bytes_free -= sp.size();
173   }
174 
NoMoreWriteToContiguousBuffer()175   void NoMoreWriteToContiguousBuffer() {
176     can_write_to_contiguous_buffer_ = false;
177   }
178 
179   // Takes a StringPiece and writes it to "permanent" storage, then returns a
180   // StringPiece which points to that data.  If block_idx != NULL, it will be
181   // assigned the index of the block into which the data was stored.
182   // Note that the 'permanent' storage in which it stores data may be in
183   // the first block IFF the NoMoreWriteToContiguousBuffer function has
184   // been called since the last Clear/Construction.
Write(const base::StringPiece & sp,Blocks::size_type * block_buffer_idx)185   base::StringPiece Write(const base::StringPiece& sp,
186                     Blocks::size_type* block_buffer_idx) {
187     if (sp.empty()) {
188       return sp;
189     }
190     char* storage = Reserve(sp.size(), block_buffer_idx);
191     memcpy(storage, sp.data(), sp.size());
192     return base::StringPiece(storage, sp.size());
193   }
194 
195   // Reserves "permanent" storage of the size indicated. Returns a pointer to
196   // the beginning of that storage, and assigns the index of the block used to
197   // block_buffer_idx. This function uses the first block IFF the
198   // NoMoreWriteToContiguousBuffer function has been called since the last
199   // Clear/Construction.
Reserve(size_t size,Blocks::size_type * block_buffer_idx)200   char* Reserve(size_t size,
201                 Blocks::size_type* block_buffer_idx) {
202     // There should always be a 'first_block', even if it
203     // contains nothing.
204     DCHECK_GE(blocks_.size(), 1u);
205     BufferBlock* block = NULL;
206     Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
207     for (; block_idx < blocks_.size(); ++block_idx) {
208       if (blocks_[block_idx].bytes_free >= size) {
209         block = &blocks_[block_idx];
210         break;
211       }
212     }
213     if (block == NULL) {
214       if (blocksize_ < size) {
215         blocks_.push_back(AllocCustomBlock(size));
216       } else {
217         blocks_.push_back(AllocBlock());
218       }
219       block = &blocks_.back();
220     }
221 
222     char* storage = block->start_of_unused_bytes();
223     block->bytes_free -= size;
224     if (block_buffer_idx) {
225       *block_buffer_idx = block_idx;
226     }
227     return storage;
228   }
229 
Clear()230   void Clear() {
231     CHECK(!blocks_.empty());
232     if (blocksize_ == blocks_[0].buffer_size) {
233       CleanupBlocksStartingFrom(1);
234       blocks_[0].bytes_free = blocks_[0].buffer_size;
235     } else {
236       CleanupBlocksStartingFrom(0);
237       blocks_.push_back(AllocBlock());
238     }
239     DCHECK_GE(blocks_.size(), 1u);
240     can_write_to_contiguous_buffer_ = true;
241   }
242 
Swap(BalsaBuffer * b)243   void Swap(BalsaBuffer* b) {
244     blocks_.swap(b->blocks_);
245     std::swap(can_write_to_contiguous_buffer_,
246               b->can_write_to_contiguous_buffer_);
247     std::swap(blocksize_, b->blocksize_);
248   }
249 
CopyFrom(const BalsaBuffer & b)250   void CopyFrom(const BalsaBuffer& b) {
251     CleanupBlocksStartingFrom(0);
252     blocks_.resize(b.blocks_.size());
253     for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
254       blocks_[i] = CopyBlock(b.blocks_[i]);
255     }
256     blocksize_ = b.blocksize_;
257     can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
258   }
259 
StartOfFirstBlock()260   const char* StartOfFirstBlock() const {
261     return blocks_[0].buffer;
262   }
263 
EndOfFirstBlock()264   const char* EndOfFirstBlock() const {
265     return blocks_[0].buffer + blocks_[0].bytes_used();
266   }
267 
can_write_to_contiguous_buffer()268   bool can_write_to_contiguous_buffer() const {
269     return can_write_to_contiguous_buffer_;
270   }
blocksize()271   size_t blocksize() const { return blocksize_; }
num_blocks()272   Blocks::size_type num_blocks() const { return blocks_.size(); }
buffer_size(size_t idx)273   size_t buffer_size(size_t idx) const { return blocks_[idx].buffer_size; }
bytes_used(size_t idx)274   size_t bytes_used(size_t idx) const { return blocks_[idx].bytes_used(); }
275 
276  protected:
BalsaBuffer()277   BalsaBuffer() :
278       blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {
279     blocks_.push_back(AllocBlock());
280   }
281 
BalsaBuffer(size_t blocksize)282   explicit BalsaBuffer(size_t blocksize) :
283       blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {
284     blocks_.push_back(AllocBlock());
285   }
286 
AllocBlock()287   BufferBlock AllocBlock() {
288     return AllocCustomBlock(blocksize_);
289   }
290 
AllocCustomBlock(size_t blocksize)291   BufferBlock AllocCustomBlock(size_t blocksize) {
292     return BufferBlock(new char[blocksize], blocksize, blocksize);
293   }
294 
CopyBlock(const BufferBlock & b)295   BufferBlock CopyBlock(const BufferBlock& b) {
296     BufferBlock block = b;
297     if (b.buffer == NULL) {
298       return block;
299     }
300 
301     block.buffer = new char[b.buffer_size];
302     memcpy(block.buffer, b.buffer, b.bytes_used());
303     return block;
304   }
305 
306   // Cleans up the object.
307   // The block at start_idx, and all subsequent blocks
308   // will be cleared and have associated memory deleted.
CleanupBlocksStartingFrom(Blocks::size_type start_idx)309   void CleanupBlocksStartingFrom(Blocks::size_type start_idx) {
310     for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) {
311       delete[] blocks_[i].buffer;
312     }
313     blocks_.resize(start_idx);
314   }
315 
316   // A container of BufferBlocks
317   Blocks blocks_;
318 
319   // The default allocation size for a block.
320   // In general, blocksize_ bytes will be allocated for
321   // each buffer.
322   size_t blocksize_;
323 
324   // If set to true, then the first block cannot be used for Write() calls as
325   // the WriteToContiguous... function will modify the base pointer for this
326   // block, and the Write() calls need to be sure that the base pointer will
327   // not be changing in order to provide the user with StringPieces which
328   // continue to be valid.
329   bool can_write_to_contiguous_buffer_;
330 };
331 
332 ////////////////////////////////////////////////////////////////////////////////
333 
334 // All of the functions in the BalsaHeaders class use string pieces, by either
335 // using the StringPiece class, or giving an explicit size and char* (as these
336 // are the native representation for these string pieces).
337 // This is done for several reasons.
338 //  1) This minimizes copying/allocation/deallocation as compared to using
339 //  string parameters
340 //  2) This reduces the number of strlen() calls done (as the length of any
341 //  string passed in is relatively likely to be known at compile time, and for
342 //  those strings passed back we obviate the need for a strlen() to determine
343 //  the size of new storage allocations if a new allocation is required.
344 //  3) This class attempts to store all of its data in two linear buffers in
345 //  order to enhance the speed of parsing and writing out to a buffer. As a
346 //  result, many string pieces are -not- terminated by '\0', and are not
347 //  c-strings.  Since this is the case, we must delineate the length of the
348 //  string explicitly via a length.
349 //
350 //  WARNING:  The side effect of using StringPiece is that if the underlying
351 //  buffer changes (due to modifying the headers) the StringPieces which point
352 //  to the data which was modified, may now contain "garbage", and should not
353 //  be dereferenced.
354 //  For example, If you fetch some component of the first-line, (request or
355 //  response), and then you modify the first line, the StringPieces you
356 //  originally received from the original first-line may no longer be valid).
357 //
358 //  StringPieces pointing to pieces of header lines which have not been
359 //  erased() or modified should be valid until the object is cleared or
360 //  destroyed.
361 
362 class BalsaHeaders {
363  public:
364   struct HeaderLineDescription {
HeaderLineDescriptionHeaderLineDescription365     HeaderLineDescription(size_t first_character_index,
366                           size_t key_end_index,
367                           size_t value_begin_index,
368                           size_t last_character_index,
369                           size_t buffer_base_index) :
370         first_char_idx(first_character_index),
371         key_end_idx(key_end_index),
372         value_begin_idx(value_begin_index),
373         last_char_idx(last_character_index),
374         buffer_base_idx(buffer_base_index),
375         skip(false) {}
376 
HeaderLineDescriptionHeaderLineDescription377     HeaderLineDescription() :
378         first_char_idx(0),
379         key_end_idx(0),
380         value_begin_idx(0),
381         last_char_idx(0),
382         buffer_base_idx(0),
383         skip(false) {}
384 
385     size_t first_char_idx;
386     size_t key_end_idx;
387     size_t value_begin_idx;
388     size_t last_char_idx;
389     BalsaBuffer::Blocks::size_type buffer_base_idx;
390     bool skip;
391   };
392 
393   typedef std::vector<base::StringPiece> HeaderTokenList;
394   friend bool net::ParseHTTPFirstLine(const char* begin,
395                                        const char* end,
396                                        bool is_request,
397                                        size_t max_request_uri_length,
398                                        BalsaHeaders* headers,
399                                        BalsaFrameEnums::ErrorCode* error_code);
400 
401  protected:
402   typedef std::vector<HeaderLineDescription> HeaderLines;
403 
404   // Why these base classes (iterator_base, reverse_iterator_base)?  Well, if
405   // we do want to export both iterator and const_iterator types (currently we
406   // only have const_iterator), then this is useful to avoid code duplication.
407   // Additionally, having this base class makes comparisons of iterators of
408   // different types (they're different types to ensure that operator= and
409   // constructors do not work in the places where they're expected to not work)
410   // work properly. There could be as many as 4 iterator types, all based on
411   // the same data as iterator_base... so it makes sense to simply have some
412   // base classes.
413 
414   class iterator_base {
415    public:
416     friend class BalsaHeaders;
417     friend class reverse_iterator_base;
418     typedef std::pair<base::StringPiece, base::StringPiece> StringPiecePair;
419     typedef StringPiecePair value_type;
420     typedef value_type& reference;
421     typedef value_type* pointer;
422 
423     typedef std::forward_iterator_tag iterator_category;
424     typedef ptrdiff_t difference_type;
425 
426     typedef iterator_base self;
427 
428     // default constructor.
iterator_base()429     iterator_base() : headers_(NULL), idx_(0) { }
430 
431     // copy constructor.
iterator_base(const iterator_base & it)432     iterator_base(const iterator_base& it)
433       : headers_(it.headers_),
434         idx_(it.idx_) {}
435 
436     reference operator*() const {
437       return Lookup(idx_);
438     }
439 
440     pointer operator->() const {
441       return &(this->operator*());
442     }
443 
444     bool operator==(const self& it) const {
445       return idx_ == it.idx_;
446     }
447 
448     bool operator<(const self& it) const {
449       return idx_ < it.idx_;
450     }
451 
452     bool operator<=(const self& it) const {
453       return idx_ <= it.idx_;
454     }
455 
456     bool operator!=(const self& it) const {
457       return !(*this == it);
458     }
459 
460     bool operator>(const self& it) const {
461       return it < *this;
462     }
463 
464     bool operator>=(const self& it) const {
465       return it <= *this;
466     }
467 
468     // This mainly exists so that we can have interesting output for
469     // unittesting. The EXPECT_EQ, EXPECT_NE functions require that
470     // operator<< work for the classes it sees.  It would be better if there
471     // was an additional traits-like system for the gUnit output... but oh
472     // well.
473     friend std::ostream& operator<<(std::ostream& os, const iterator_base& it) {
474       os << "[" << it.headers_ << ", " << it.idx_ << "]";
475       return os;
476     }
477 
478    protected:
iterator_base(const BalsaHeaders * headers,HeaderLines::size_type index)479     iterator_base(const BalsaHeaders* headers, HeaderLines::size_type index) :
480         headers_(headers),
481         idx_(index) {}
482 
increment()483     void increment() {
484       const HeaderLines& header_lines = headers_->header_lines_;
485       const HeaderLines::size_type header_lines_size = header_lines.size();
486       const HeaderLines::size_type original_idx = idx_;
487       do {
488         ++idx_;
489       } while (idx_ < header_lines_size && header_lines[idx_].skip == true);
490       // The condition below exists so that ++(end() - 1) == end(), even
491       // if there are only 'skip == true' elements between the end() iterator
492       // and the end of the vector of HeaderLineDescriptions.
493       // TODO(fenix): refactor this list so that we don't have to do
494       // linear scanning through skipped headers (and this condition is
495       // then unnecessary)
496       if (idx_ == header_lines_size) {
497         idx_ = original_idx + 1;
498       }
499     }
500 
decrement()501     void decrement() {
502       const HeaderLines& header_lines = headers_->header_lines_;
503       const HeaderLines::size_type header_lines_size = header_lines.size();
504       const HeaderLines::size_type original_idx = idx_;
505       do {
506         --idx_;
507       } while (idx_ >= 0 &&
508               idx_ < header_lines_size &&
509               header_lines[idx_].skip == true);
510       // The condition below exists so that --(rbegin() + 1) == rbegin(), even
511       // if there are only 'skip == true' elements between the rbegin() iterator
512       // and the beginning of the vector of HeaderLineDescriptions.
513       // TODO(fenix): refactor this list so that we don't have to do
514       // linear scanning through skipped headers (and this condition is
515       // then unnecessary)
516       if (idx_ < 0 || idx_ > header_lines_size) {
517         idx_ = original_idx - 1;
518       }
519     }
520 
Lookup(HeaderLines::size_type index)521     reference Lookup(HeaderLines::size_type index) const {
522       DCHECK_LT(index, headers_->header_lines_.size());
523       const HeaderLineDescription& line = headers_->header_lines_[index];
524       const char* stream_begin = headers_->GetPtr(line.buffer_base_idx);
525       value_ = value_type(
526           base::StringPiece(stream_begin + line.first_char_idx,
527                       line.key_end_idx - line.first_char_idx),
528           base::StringPiece(stream_begin + line.value_begin_idx,
529                       line.last_char_idx - line.value_begin_idx));
530       DCHECK_GE(line.key_end_idx, line.first_char_idx);
531       DCHECK_GE(line.last_char_idx, line.value_begin_idx);
532       return value_;
533     }
534 
535     const BalsaHeaders* headers_;
536     HeaderLines::size_type idx_;
537     mutable StringPiecePair value_;
538   };
539 
540   class reverse_iterator_base : public iterator_base {
541    public:
542     typedef reverse_iterator_base self;
543     typedef iterator_base::reference reference;
544     typedef iterator_base::pointer pointer;
545     using iterator_base::headers_;
546     using iterator_base::idx_;
547 
reverse_iterator_base()548     reverse_iterator_base() : iterator_base() {}
549 
550     // This constructor is no explicit purposely.
reverse_iterator_base(const iterator_base & it)551     reverse_iterator_base(const iterator_base& it) :  // NOLINT
552         iterator_base(it) {
553     }
554 
555     self& operator=(const iterator_base& it) {
556       idx_ = it.idx_;
557       headers_ = it.headers_;
558       return *this;
559     }
560 
561     self& operator=(const reverse_iterator_base& it) {
562       idx_ = it.idx_;
563       headers_ = it.headers_;
564       return *this;
565     }
566 
567     reference operator*() const {
568       return Lookup(idx_ - 1);
569     }
570 
571     pointer operator->() const {
572       return &(this->operator*());
573     }
574 
reverse_iterator_base(const reverse_iterator_base & it)575     reverse_iterator_base(const reverse_iterator_base& it) :
576         iterator_base(it) { }
577 
578    protected:
increment()579     void increment() {
580       --idx_;
581       iterator_base::decrement();
582       ++idx_;
583     }
584 
decrement()585     void decrement() {
586       ++idx_;
587       iterator_base::increment();
588       --idx_;
589     }
590 
reverse_iterator_base(const BalsaHeaders * headers,HeaderLines::size_type index)591     reverse_iterator_base(const BalsaHeaders* headers,
592                           HeaderLines::size_type index) :
593         iterator_base(headers, index) {}
594   };
595 
596  public:
597   class const_header_lines_iterator : public iterator_base {
598     friend class BalsaHeaders;
599    public:
600     typedef const_header_lines_iterator self;
const_header_lines_iterator()601     const_header_lines_iterator() : iterator_base() {}
602 
const_header_lines_iterator(const const_header_lines_iterator & it)603     const_header_lines_iterator(const const_header_lines_iterator& it) :
604         iterator_base(it.headers_, it.idx_) {}
605 
606     self& operator++() {
607       iterator_base::increment();
608       return *this;
609     }
610 
611     self& operator--() {
612       iterator_base::decrement();
613       return *this;
614     }
615    protected:
const_header_lines_iterator(const BalsaHeaders * headers,HeaderLines::size_type index)616     const_header_lines_iterator(const BalsaHeaders* headers,
617                                 HeaderLines::size_type index) :
618         iterator_base(headers, index) {}
619   };
620 
621   class const_reverse_header_lines_iterator : public reverse_iterator_base {
622    public:
623     typedef const_reverse_header_lines_iterator self;
const_reverse_header_lines_iterator()624     const_reverse_header_lines_iterator() : reverse_iterator_base() {}
625 
const_reverse_header_lines_iterator(const const_header_lines_iterator & it)626     const_reverse_header_lines_iterator(
627       const const_header_lines_iterator& it) :
628         reverse_iterator_base(it.headers_, it.idx_) {}
629 
const_reverse_header_lines_iterator(const const_reverse_header_lines_iterator & it)630     const_reverse_header_lines_iterator(
631       const const_reverse_header_lines_iterator& it) :
632         reverse_iterator_base(it.headers_, it.idx_) {}
633 
base()634     const_header_lines_iterator base() {
635       return const_header_lines_iterator(headers_, idx_);
636     }
637 
638     self& operator++() {
639       reverse_iterator_base::increment();
640       return *this;
641     }
642 
643     self& operator--() {
644       reverse_iterator_base::decrement();
645       return *this;
646     }
647    protected:
const_reverse_header_lines_iterator(const BalsaHeaders * headers,HeaderLines::size_type index)648     const_reverse_header_lines_iterator(const BalsaHeaders* headers,
649                                         HeaderLines::size_type index) :
650         reverse_iterator_base(headers, index) {}
651 
652     friend class BalsaHeaders;
653   };
654 
655   // An iterator that only stops at lines with a particular key.
656   // See also GetIteratorForKey.
657   //
658   // Check against header_lines_key_end() to determine when iteration is
659   // finished. header_lines_end() will also work.
660   class const_header_lines_key_iterator : public iterator_base {
661     friend class BalsaHeaders;
662    public:
663     typedef const_header_lines_key_iterator self;
664 
665     self& operator++() {
666       do {
667         iterator_base::increment();
668       } while (!AtEnd() &&
669                !StringPieceUtils::EqualIgnoreCase(key_, (**this).first));
670       return *this;
671     }
672 
673     void operator++(int ignore) {
674       ++(*this);
675     }
676 
677     // Only forward-iteration makes sense, so no operator-- defined.
678 
679    private:
const_header_lines_key_iterator(const BalsaHeaders * headers,HeaderLines::size_type index,const base::StringPiece & key)680     const_header_lines_key_iterator(const BalsaHeaders* headers,
681                                     HeaderLines::size_type index,
682                                     const base::StringPiece& key)
683         : iterator_base(headers, index),
684           key_(key) {
685     }
686 
687     // Should only be used for creating an end iterator.
const_header_lines_key_iterator(const BalsaHeaders * headers,HeaderLines::size_type index)688     const_header_lines_key_iterator(const BalsaHeaders* headers,
689                                     HeaderLines::size_type index)
690         : iterator_base(headers, index) {
691     }
692 
AtEnd()693     bool AtEnd() const {
694       return *this >= headers_->header_lines_end();
695     }
696 
697     base::StringPiece key_;
698   };
699 
700   // TODO(fenix): Revisit the amount of bytes initially allocated to the second
701   // block of the balsa_buffer_. It may make sense to pre-allocate some amount
702   // (roughly the amount we'd append in new headers such as X-User-Ip, etc.)
BalsaHeaders()703   BalsaHeaders() :
704       balsa_buffer_(4096),
705       content_length_(0),
706       content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
707       parsed_response_code_(0),
708       firstline_buffer_base_idx_(0),
709       whitespace_1_idx_(0),
710       non_whitespace_1_idx_(0),
711       whitespace_2_idx_(0),
712       non_whitespace_2_idx_(0),
713       whitespace_3_idx_(0),
714       non_whitespace_3_idx_(0),
715       whitespace_4_idx_(0),
716       end_of_firstline_idx_(0),
717       transfer_encoding_is_chunked_(false) { }
718 
header_lines_begin()719   const_header_lines_iterator header_lines_begin() {
720     return HeaderLinesBeginHelper<const_header_lines_iterator>();
721   }
722 
header_lines_begin()723   const_header_lines_iterator header_lines_begin() const {
724     return HeaderLinesBeginHelper<const_header_lines_iterator>();
725   }
726 
header_lines_end()727   const_header_lines_iterator header_lines_end() {
728     return HeaderLinesEndHelper<const_header_lines_iterator>();
729   }
730 
header_lines_end()731   const_header_lines_iterator header_lines_end() const {
732     return HeaderLinesEndHelper<const_header_lines_iterator>();
733   }
734 
header_lines_rbegin()735   const_reverse_header_lines_iterator header_lines_rbegin() {
736     return const_reverse_header_lines_iterator(header_lines_end());
737   }
738 
header_lines_rbegin()739   const_reverse_header_lines_iterator header_lines_rbegin() const {
740     return const_reverse_header_lines_iterator(header_lines_end());
741   }
742 
header_lines_rend()743   const_reverse_header_lines_iterator header_lines_rend() {
744     return const_reverse_header_lines_iterator(header_lines_begin());
745   }
746 
header_lines_rend()747   const_reverse_header_lines_iterator header_lines_rend() const {
748     return const_reverse_header_lines_iterator(header_lines_begin());
749   }
750 
header_lines_key_end()751   const_header_lines_key_iterator header_lines_key_end() const {
752     return HeaderLinesEndHelper<const_header_lines_key_iterator>();
753   }
754 
erase(const const_header_lines_iterator & it)755   void erase(const const_header_lines_iterator& it) {
756     DCHECK_EQ(it.headers_, this);
757     DCHECK_LT(it.idx_, header_lines_.size());
758     DCHECK_GE(it.idx_, 0u);
759     header_lines_[it.idx_].skip = true;
760   }
761 
762   void Clear();
763 
764   void Swap(BalsaHeaders* other);
765 
766   void CopyFrom(const BalsaHeaders& other);
767 
768   void HackHeader(const base::StringPiece& key, const base::StringPiece& value);
769 
770   // Same as AppendToHeader, except that it will attempt to preserve
771   // header ordering.
772   // Note that this will always append to an existing header, if available,
773   // without moving the header around, or collapsing multiple header lines
774   // with the same key together. For this reason, it only 'attempts' to
775   // preserve header ordering.
776   // TODO(fenix): remove this function and rename all occurances
777   // of it in the code to AppendToHeader when the condition above
778   // has been satisified.
779   void HackAppendToHeader(const base::StringPiece& key,
780                           const base::StringPiece& value);
781 
782   // Replaces header entries with key 'key' if they exist, or appends
783   // a new header if none exist.  See 'AppendHeader' below for additional
784   // comments about ContentLength and TransferEncoding headers. Note that this
785   // will allocate new storage every time that it is called.
786   // TODO(fenix): modify this function to reuse existing storage
787   // if it is available.
788   void ReplaceOrAppendHeader(const base::StringPiece& key,
789                              const base::StringPiece& value);
790 
791   // Append a new header entry to the header object. Clients who wish to append
792   // Content-Length header should use SetContentLength() method instead of
793   // adding the content length header using AppendHeader (manually adding the
794   // content length header will not update the content_length_ and
795   // content_length_status_ values).
796   // Similarly, clients who wish to add or remove the transfer encoding header
797   // in order to apply or remove chunked encoding should use SetChunkEncoding()
798   // instead.
799   void AppendHeader(const base::StringPiece& key,
800                     const base::StringPiece& value);
801 
802   // Appends ',value' to an existing header named 'key'.  If no header with the
803   // correct key exists, it will call AppendHeader(key, value).  Calling this
804   // function on a key which exists several times in the headers will produce
805   // unpredictable results.
806   void AppendToHeader(const base::StringPiece& key,
807                       const base::StringPiece& value);
808 
809   // Prepends 'value,' to an existing header named 'key'.  If no header with the
810   // correct key exists, it will call AppendHeader(key, value).  Calling this
811   // function on a key which exists several times in the headers will produce
812   // unpredictable results.
813   void PrependToHeader(const base::StringPiece& key,
814                        const base::StringPiece& value);
815 
816   const base::StringPiece GetHeader(const base::StringPiece& key) const;
817 
818   // Iterates over all currently valid header lines, appending their
819   // values into the vector 'out', in top-to-bottom order.
820   // Header-lines which have been erased are not currently valid, and
821   // will not have their values appended. Empty values will be
822   // represented as empty string. If 'key' doesn't exist in the headers at
823   // all, out will not be changed. We do not clear the vector out
824   // before adding new entries. If there are header lines with matching
825   // key but empty value then they are also added to the vector out.
826   // (Basically empty values are not treated in any special manner).
827   //
828   // Example:
829   // Input header:
830   // "GET / HTTP/1.0\r\n"
831   //    "key1: v1\r\n"
832   //    "key1: \r\n"
833   //    "key1:\r\n"
834   //    "key1:  v1\r\n"
835   //    "key1:v2\r\n"
836   //
837   //  vector out is initially: ["foo"]
838   //  vector out after GetAllOfHeader("key1", &out) is:
839   // ["foo", "v1", "", "", "v2", "v1", "v2"]
840 
841   void GetAllOfHeader(const base::StringPiece& key,
842                       std::vector<base::StringPiece>* out) const;
843 
844   // Joins all values for key into a comma-separated string in out.
845   // More efficient than calling JoinStrings on result of GetAllOfHeader if
846   // you don't need the intermediate vector<StringPiece>.
847   void GetAllOfHeaderAsString(const base::StringPiece& key,
848                               std::string* out) const;
849 
850   // Returns true if RFC 2616 Section 14 indicates that header can
851   // have multiple values.
852   static bool IsMultivaluedHeader(const base::StringPiece& header);
853 
854   // Determine if a given header is present.
HasHeader(const base::StringPiece & key)855   inline bool HasHeader(const base::StringPiece& key) const {
856     return (GetConstHeaderLinesIterator(key, header_lines_.begin()) !=
857             header_lines_.end());
858   }
859 
860   // Returns true iff any header 'key' exists with non-empty value.
861   bool HasNonEmptyHeader(const base::StringPiece& key) const;
862 
863   const_header_lines_iterator GetHeaderPosition(
864       const base::StringPiece& key) const;
865 
866   // Returns a forward-only iterator that only stops at lines matching key.
867   // String backing 'key' must remain valid for lifetime of iterator.
868   //
869   // Check returned iterator against header_lines_key_end() to determine when
870   // iteration is finished.
871   const_header_lines_key_iterator GetIteratorForKey(
872       const base::StringPiece& key) const;
873 
874   void RemoveAllOfHeader(const base::StringPiece& key);
875 
876   // Removes all headers starting with 'key' [case insensitive]
877   void RemoveAllHeadersWithPrefix(const base::StringPiece& key);
878 
879   // Returns the lower bound of memory  used by this header object, including
880   // all internal buffers and data structure. Some of the memory used cannot be
881   // directly measure. For example, memory used for bookkeeping by standard
882   // containers.
883   size_t GetMemoryUsedLowerBound() const;
884 
885   // Returns the upper bound on the required buffer space to fully write out
886   // the header object (this include the first line, all header lines, and the
887   // final CRLF that marks the ending of the header).
888   size_t GetSizeForWriteBuffer() const;
889 
890   // The following WriteHeader* methods are template member functions that
891   // place one requirement on the Buffer class: it must implement a Write
892   // method that takes a pointer and a length. The buffer passed in is not
893   // required to be stretchable. For non-stretchable buffers, the user must
894   // call GetSizeForWriteBuffer() to find out the upper bound on the output
895   // buffer space required to make sure that the entire header is serialized.
896   // BalsaHeaders will not check that there is adequate space in the buffer
897   // object during the write.
898 
899   // Writes the entire header and the final CRLF that marks the end of the HTTP
900   // header section to the buffer. After this method returns, no more header
901   // data should be written to the buffer.
902   template <typename Buffer>
WriteHeaderAndEndingToBuffer(Buffer * buffer)903   void WriteHeaderAndEndingToBuffer(Buffer* buffer) const {
904     WriteToBuffer(buffer);
905     WriteHeaderEndingToBuffer(buffer);
906   }
907 
908   // Writes the final CRLF to the buffer to terminate the HTTP header section.
909   // After this method returns, no more header data should be written to the
910   // buffer.
911   template <typename Buffer>
WriteHeaderEndingToBuffer(Buffer * buffer)912   static void WriteHeaderEndingToBuffer(Buffer* buffer) {
913     buffer->Write("\r\n", 2);
914   }
915 
916   // Writes the entire header to the buffer without the CRLF that terminates
917   // the HTTP header. This lets users append additional header lines using
918   // WriteHeaderLineToBuffer and then terminate the header with
919   // WriteHeaderEndingToBuffer as the header is serialized to the
920   // buffer, without having to first copy the header.
921   template <typename Buffer>
WriteToBuffer(Buffer * buffer)922   void WriteToBuffer(Buffer* buffer) const {
923     // write the first line.
924     const size_t firstline_len = whitespace_4_idx_ - non_whitespace_1_idx_;
925     const char* stream_begin = GetPtr(firstline_buffer_base_idx_);
926     buffer->Write(stream_begin + non_whitespace_1_idx_, firstline_len);
927     buffer->Write("\r\n", 2);
928     const HeaderLines::size_type end = header_lines_.size();
929     for (HeaderLines::size_type i = 0; i < end; ++i) {
930       const HeaderLineDescription& line = header_lines_[i];
931       if (line.skip) {
932         continue;
933       }
934       const char* line_ptr = GetPtr(line.buffer_base_idx);
935       WriteHeaderLineToBuffer(
936           buffer,
937           base::StringPiece(line_ptr + line.first_char_idx,
938                       line.key_end_idx - line.first_char_idx),
939           base::StringPiece(line_ptr + line.value_begin_idx,
940                       line.last_char_idx - line.value_begin_idx));
941     }
942   }
943 
944   // Takes a header line in the form of a key/value pair and append it to the
945   // buffer. This function should be called after WriteToBuffer to
946   // append additional header lines to the header without copying the header.
947   // When the user is done with appending to the buffer,
948   // WriteHeaderEndingToBuffer must be used to terminate the HTTP
949   // header in the buffer. This method is a no-op if key is empty.
950   template <typename Buffer>
WriteHeaderLineToBuffer(Buffer * buffer,const base::StringPiece & key,const base::StringPiece & value)951   static void WriteHeaderLineToBuffer(Buffer* buffer,
952                                       const base::StringPiece& key,
953                                       const base::StringPiece& value) {
954     // if the key is empty, we don't want to write the rest because it
955     // will not be a well-formed header line.
956     if (key.size() > 0) {
957       buffer->Write(key.data(), key.size());
958       buffer->Write(": ", 2);
959       buffer->Write(value.data(), value.size());
960       buffer->Write("\r\n", 2);
961     }
962   }
963 
964   // Dump the textural representation of the header object to a string, which
965   // is suitable for writing out to logs. All CRLF will be printed out as \n.
966   // This function can be called on a header object in any state. Raw header
967   // data will be printed out if the header object is not completely parsed,
968   // e.g., when there was an error in the middle of parsing.
969   // The header content is appended to the string; the original content is not
970   // cleared.
971   void DumpToString(std::string* str) const;
972 
first_line()973   const base::StringPiece first_line() const {
974     DCHECK_GE(whitespace_4_idx_, non_whitespace_1_idx_);
975     return base::StringPiece(BeginningOfFirstLine() + non_whitespace_1_idx_,
976                        whitespace_4_idx_ - non_whitespace_1_idx_);
977   }
978 
979   // Returns the parsed value of the response code if it has been parsed.
980   // Guaranteed to return 0 when unparsed (though it is a much better idea to
981   // verify that the BalsaFrame had no errors while parsing).
982   // This may return response codes which are outside the normal bounds of
983   // HTTP response codes-- it is up to the user of this class to ensure that
984   // the response code is one which is interpretable.
parsed_response_code()985   size_t parsed_response_code() const { return parsed_response_code_; }
986 
request_method()987   const base::StringPiece request_method() const {
988     DCHECK_GE(whitespace_2_idx_, non_whitespace_1_idx_);
989     return base::StringPiece(BeginningOfFirstLine() + non_whitespace_1_idx_,
990                        whitespace_2_idx_ - non_whitespace_1_idx_);
991   }
992 
response_version()993   const base::StringPiece response_version() const {
994     // Note: There is no difference between request_method() and
995     // response_version(). They both could be called
996     // GetFirstTokenFromFirstline()... but that wouldn't be anywhere near as
997     // descriptive.
998     return request_method();
999   }
1000 
request_uri()1001   const base::StringPiece request_uri() const {
1002     DCHECK_GE(whitespace_3_idx_, non_whitespace_2_idx_);
1003     return base::StringPiece(BeginningOfFirstLine() + non_whitespace_2_idx_,
1004                        whitespace_3_idx_ - non_whitespace_2_idx_);
1005   }
1006 
response_code()1007   const base::StringPiece response_code() const {
1008     // Note: There is no difference between request_uri() and response_code().
1009     // They both could be called GetSecondtTokenFromFirstline(), but, as noted
1010     // in an earlier comment, that wouldn't be as descriptive.
1011     return request_uri();
1012   }
1013 
request_version()1014   const base::StringPiece request_version() const {
1015     DCHECK_GE(whitespace_4_idx_, non_whitespace_3_idx_);
1016     return base::StringPiece(BeginningOfFirstLine() + non_whitespace_3_idx_,
1017                        whitespace_4_idx_ - non_whitespace_3_idx_);
1018   }
1019 
response_reason_phrase()1020   const base::StringPiece response_reason_phrase() const {
1021     // Note: There is no difference between request_version() and
1022     // response_reason_phrase(). They both could be called
1023     // GetThirdTokenFromFirstline(), but, as noted in an earlier comment, that
1024     // wouldn't be as descriptive.
1025     return request_version();
1026   }
1027 
1028   // Note that SetFirstLine will not update the internal indices for the
1029   // various bits of the first-line (and may set them all to zero).
1030   // If you'd like to use the accessors for the various bits of the firstline,
1031   // then you should use the Set* functions, or SetFirstlineFromStringPieces,
1032   // below, instead.
1033   //
1034   void SetFirstlineFromStringPieces(const base::StringPiece& firstline_a,
1035                                     const base::StringPiece& firstline_b,
1036                                     const base::StringPiece& firstline_c);
1037 
SetRequestFirstlineFromStringPieces(const base::StringPiece & method,const base::StringPiece & uri,const base::StringPiece & version)1038   void SetRequestFirstlineFromStringPieces(const base::StringPiece& method,
1039                                            const base::StringPiece& uri,
1040                                            const base::StringPiece& version) {
1041     SetFirstlineFromStringPieces(method, uri, version);
1042   }
1043 
SetResponseFirstlineFromStringPieces(const base::StringPiece & version,const base::StringPiece & code,const base::StringPiece & reason_phrase)1044   void SetResponseFirstlineFromStringPieces(
1045       const base::StringPiece& version,
1046       const base::StringPiece& code,
1047       const base::StringPiece& reason_phrase) {
1048     SetFirstlineFromStringPieces(version, code, reason_phrase);
1049   }
1050 
1051   // These functions are exactly the same, except that their names are
1052   // different. This is done so that the code using this class is more
1053   // expressive.
1054   void SetRequestMethod(const base::StringPiece& method);
1055   void SetResponseVersion(const base::StringPiece& version);
1056 
1057   void SetRequestUri(const base::StringPiece& uri);
1058   void SetResponseCode(const base::StringPiece& code);
set_parsed_response_code(size_t parsed_response_code)1059   void set_parsed_response_code(size_t parsed_response_code) {
1060     parsed_response_code_ = parsed_response_code;
1061   }
1062   void SetParsedResponseCodeAndUpdateFirstline(size_t parsed_response_code);
1063 
1064   // These functions are exactly the same, except that their names are
1065   // different. This is done so that the code using this class is more
1066   // expressive.
1067   void SetRequestVersion(const base::StringPiece& version);
1068   void SetResponseReasonPhrase(const base::StringPiece& reason_phrase);
1069 
1070   // The biggest problem with SetFirstLine is that we don't want to use a
1071   // separate buffer for it.  The second biggest problem with it is that the
1072   // first biggest problem requires that we store offsets into a buffer instead
1073   // of pointers into a buffer. Cuteness aside, SetFirstLine doesn't parse
1074   // the individual fields of the firstline, and so accessors to those fields
1075   // will not work properly after calling SetFirstLine. If you want those
1076   // accessors to work, use the Set* functions above this one.
1077   // SetFirstLine is stuff useful, however, if all you care about is correct
1078   // serialization with the rest of the header object.
1079   void SetFirstLine(const base::StringPiece& line);
1080 
1081   // Simple accessors to some of the internal state
transfer_encoding_is_chunked()1082   bool transfer_encoding_is_chunked() const {
1083     return transfer_encoding_is_chunked_;
1084   }
1085 
ResponseCodeImpliesNoBody(int code)1086   static bool ResponseCodeImpliesNoBody(int code) {
1087     // From HTTP spec section 6.1.1 all 1xx responses must not have a body,
1088     // as well as 204 No Content and 304 Not Modified.
1089     return ((code >= 100) && (code <= 199)) || (code == 204) || (code == 304);
1090   }
1091 
1092   // Note: never check this for requests. Nothing bad will happen if you do,
1093   // but spec does not allow requests framed by connection close.
1094   // TODO(vitaliyl): refactor.
is_framed_by_connection_close()1095   bool is_framed_by_connection_close() const {
1096     // We declare that response is framed by connection close if it has no
1097     // content-length, no transfer encoding, and is allowed to have a body by
1098     // the HTTP spec.
1099     // parsed_response_code_ is 0 for requests, so ResponseCodeImpliesNoBody
1100     // will return false.
1101     return (content_length_status_ == BalsaHeadersEnums::NO_CONTENT_LENGTH) &&
1102         !transfer_encoding_is_chunked_ &&
1103         !ResponseCodeImpliesNoBody(parsed_response_code_);
1104   }
1105 
content_length()1106   size_t content_length() const { return content_length_; }
content_length_status()1107   BalsaHeadersEnums::ContentLengthStatus content_length_status() const {
1108     return content_length_status_;
1109   }
1110 
1111   // SetContentLength and SetChunkEncoding modifies the header object to use
1112   // content-length and transfer-encoding headers in a consistent manner. They
1113   // set all internal flags and status so client can get a consistent view from
1114   // various accessors.
1115   void SetContentLength(size_t length);
1116   void SetChunkEncoding(bool chunk_encode);
1117 
1118  protected:
1119   friend class BalsaFrame;
1120   friend class FlipFrame;
1121   friend class HTTPMessage;
1122   friend class BalsaHeadersTokenUtils;
1123 
BeginningOfFirstLine()1124   const char* BeginningOfFirstLine() const {
1125     return GetPtr(firstline_buffer_base_idx_);
1126   }
1127 
GetPtr(BalsaBuffer::Blocks::size_type block_idx)1128   char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) {
1129     return balsa_buffer_.GetPtr(block_idx);
1130   }
1131 
GetPtr(BalsaBuffer::Blocks::size_type block_idx)1132   const char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) const {
1133     return balsa_buffer_.GetPtr(block_idx);
1134   }
1135 
WriteFromFramer(const char * ptr,size_t size)1136   void WriteFromFramer(const char* ptr, size_t size) {
1137     balsa_buffer_.WriteToContiguousBuffer(base::StringPiece(ptr, size));
1138   }
1139 
DoneWritingFromFramer()1140   void DoneWritingFromFramer() {
1141     balsa_buffer_.NoMoreWriteToContiguousBuffer();
1142   }
1143 
OriginalHeaderStreamBegin()1144   const char* OriginalHeaderStreamBegin() const {
1145     return balsa_buffer_.StartOfFirstBlock();
1146   }
1147 
OriginalHeaderStreamEnd()1148   const char* OriginalHeaderStreamEnd() const {
1149     return balsa_buffer_.EndOfFirstBlock();
1150   }
1151 
GetReadableBytesFromHeaderStream()1152   size_t GetReadableBytesFromHeaderStream() const {
1153     return OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin();
1154   }
1155 
GetReadablePtrFromHeaderStream(const char ** p,size_t * s)1156   void GetReadablePtrFromHeaderStream(const char** p, size_t* s) {
1157     *p = OriginalHeaderStreamBegin();
1158     *s = GetReadableBytesFromHeaderStream();
1159   }
1160 
1161   base::StringPiece GetValueFromHeaderLineDescription(
1162       const HeaderLineDescription& line) const;
1163 
1164   void AddAndMakeDescription(const base::StringPiece& key,
1165                              const base::StringPiece& value,
1166                              HeaderLineDescription* d);
1167 
1168   void AppendOrPrependAndMakeDescription(const base::StringPiece& key,
1169                                          const base::StringPiece& value,
1170                                          bool append,
1171                                          HeaderLineDescription* d);
1172 
1173   // Removes all header lines with the given key starting at start.
1174   void RemoveAllOfHeaderStartingAt(const base::StringPiece& key,
1175                                    HeaderLines::iterator start);
1176 
1177   // If the 'key' does not exist in the headers, calls
1178   // AppendHeader(key, value).  Otherwise if append is true, appends ',value'
1179   // to the first existing header with key 'key'.  If append is false, prepends
1180   // 'value,' to the first existing header with key 'key'.
1181   void AppendOrPrependToHeader(const base::StringPiece& key,
1182                                const base::StringPiece& value,
1183                                bool append);
1184 
1185   HeaderLines::const_iterator GetConstHeaderLinesIterator(
1186       const base::StringPiece& key,
1187       HeaderLines::const_iterator start) const;
1188 
1189   HeaderLines::iterator GetHeaderLinesIteratorNoSkip(
1190       const base::StringPiece& key,
1191       HeaderLines::iterator start);
1192 
1193   HeaderLines::iterator GetHeaderLinesIterator(
1194       const base::StringPiece& key,
1195       HeaderLines::iterator start);
1196 
1197   template <typename IteratorType>
HeaderLinesBeginHelper()1198   const IteratorType HeaderLinesBeginHelper() const {
1199     if (header_lines_.empty()) {
1200       return IteratorType(this, 0);
1201     }
1202     const HeaderLines::size_type header_lines_size = header_lines_.size();
1203     for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) {
1204       if (header_lines_[i].skip == false) {
1205         return IteratorType(this, i);
1206       }
1207     }
1208     return IteratorType(this, 0);
1209   }
1210 
1211   template <typename IteratorType>
HeaderLinesEndHelper()1212   const IteratorType HeaderLinesEndHelper() const {
1213     if (header_lines_.empty()) {
1214       return IteratorType(this, 0);
1215     }
1216     const HeaderLines::size_type header_lines_size = header_lines_.size();
1217     HeaderLines::size_type i = header_lines_size;
1218     do {
1219       --i;
1220       if (header_lines_[i].skip == false) {
1221         return IteratorType(this, i + 1);
1222       }
1223     } while (i != 0);
1224     return IteratorType(this, 0);
1225   }
1226 
1227   // At the moment, this function will always return the original headers.
1228   // In the future, it may not do so after erasing header lines, modifying
1229   // header lines, or modifying the first line.
1230   // For this reason, it is strongly suggested that use of this function is
1231   // only acceptable for the purpose of debugging parse errors seen by the
1232   // BalsaFrame class.
OriginalHeadersForDebugging()1233   base::StringPiece OriginalHeadersForDebugging() const {
1234     return base::StringPiece(OriginalHeaderStreamBegin(),
1235                        OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin());
1236   }
1237 
1238   BalsaBuffer balsa_buffer_;
1239 
1240   size_t content_length_;
1241   BalsaHeadersEnums::ContentLengthStatus content_length_status_;
1242   size_t parsed_response_code_;
1243   // HTTP firstlines all have the following structure:
1244   //  LWS         NONWS  LWS    NONWS   LWS    NONWS   NOTCRLF  CRLF
1245   //  [\t \r\n]+ [^\t ]+ [\t ]+ [^\t ]+ [\t ]+ [^\t ]+ [^\r\n]+ "\r\n"
1246   //  ws1        nws1    ws2    nws2    ws3    nws3             ws4
1247   //  |          [-------)      [-------)      [----------------)
1248   //    REQ:     method         request_uri    version
1249   //   RESP:     version        statuscode     reason
1250   //
1251   //   The first NONWS->LWS component we'll call firstline_a.
1252   //   The second firstline_b, and the third firstline_c.
1253   //
1254   //   firstline_a goes from nws1 to (but not including) ws2
1255   //   firstline_b goes from nws2 to (but not including) ws3
1256   //   firstline_c goes from nws3 to (but not including) ws4
1257   //
1258   // In the code:
1259   //    ws1 == whitespace_1_idx_
1260   //   nws1 == non_whitespace_1_idx_
1261   //    ws2 == whitespace_2_idx_
1262   //   nws2 == non_whitespace_2_idx_
1263   //    ws3 == whitespace_3_idx_
1264   //   nws3 == non_whitespace_3_idx_
1265   //    ws4 == whitespace_4_idx_
1266   BalsaBuffer::Blocks::size_type firstline_buffer_base_idx_;
1267   size_t whitespace_1_idx_;
1268   size_t non_whitespace_1_idx_;
1269   size_t whitespace_2_idx_;
1270   size_t non_whitespace_2_idx_;
1271   size_t whitespace_3_idx_;
1272   size_t non_whitespace_3_idx_;
1273   size_t whitespace_4_idx_;
1274   size_t end_of_firstline_idx_;
1275 
1276   bool transfer_encoding_is_chunked_;
1277 
1278   HeaderLines header_lines_;
1279 };
1280 
1281 }  // namespace net
1282 
1283 #endif  // NET_TOOLS_FLIP_SERVER_BALSA_HEADERS_H_
1284 
1285