1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/balsa_headers.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm> 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <ext/hash_set> 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <utility> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/port.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_piece.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/balsa_enums.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/buffer_interface.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/simple_buffer.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "third_party/tcmalloc/chromium/src/base/googleinit.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #include "util/gtl/iterator_adaptors-inl.h" 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// #include "util/gtl/map-util.h" 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kContentLength[] = "Content-Length"; 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kTransferEncoding[] = "Transfer-Encoding"; 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char kSpaceChar = ' '; 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott__gnu_cxx::hash_set<base::StringPiece, 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::StringPieceCaseHash, 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott net::StringPieceCaseEqual> g_multivalued_headers; 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid InitMultivaluedHeaders() { 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("accept"); 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("accept-charset"); 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("accept-encoding"); 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("accept-language"); 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("accept-ranges"); 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("allow"); 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("cache-control"); 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("connection"); 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("content-encoding"); 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("content-language"); 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("expect"); 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("if-match"); 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("if-none-match"); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("pragma"); 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("proxy-authenticate"); 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("te"); 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("trailer"); 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("transfer-encoding"); 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("upgrade"); 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("vary"); 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("via"); 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("warning"); 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("www-authenticate"); 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not mentioned in RFC 2616, but it can have multiple values. 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott g_multivalued_headers.insert("set-cookie"); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottREGISTER_MODULE_INITIALIZER(multivalued_headers, InitMultivaluedHeaders()); 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int kFastToBufferSize = 32; // I think 22 is adequate, but anyway.. 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst size_t BalsaBuffer::kDefaultBlocksize; 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickstd::ostream& BalsaHeaders::iterator_base::operator<<(std::ostream& os) const { 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick os << "[" << this->headers_ << ", " << this->idx_ << "]"; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return os; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaBuffer::~BalsaBuffer() { 7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CleanupBlocksStartingFrom(0); 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Returns the total amount of memory used by the buffer blocks. 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensize_t BalsaBuffer::GetTotalBufferBlockSize() const { 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t buffer_size = 0; 8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (Blocks::const_iterator iter = blocks_.begin(); 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen iter != blocks_.end(); 8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ++iter) { 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen buffer_size += iter->buffer_size; 8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return buffer_size; 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BalsaBuffer::WriteToContiguousBuffer(const base::StringPiece& sp) { 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (sp.empty()) { 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHECK(can_write_to_contiguous_buffer_); 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_GE(blocks_.size(), 1u); 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (blocks_[0].buffer == NULL && sp.size() <= blocksize_) { 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[0] = AllocBlock(); 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size()); 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (blocks_[0].bytes_free < sp.size()) { 10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the first block isn't big enough, resize it. 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const size_t old_storage_size_used = blocks_[0].bytes_used(); 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const size_t new_storage_size = old_storage_size_used + sp.size(); 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char* new_storage = new char[new_storage_size]; 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char* old_storage = blocks_[0].buffer; 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (old_storage_size_used) { 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(new_storage, old_storage, old_storage_size_used); 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(new_storage + old_storage_size_used, sp.data(), sp.size()); 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[0].buffer = new_storage; 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[0].bytes_free = sp.size(); 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[0].buffer_size = new_storage_size; 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete[] old_storage; 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size()); 11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[0].bytes_free -= sp.size(); 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbase::StringPiece BalsaBuffer::Write(const base::StringPiece& sp, 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Blocks::size_type* block_buffer_idx) { 12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (sp.empty()) { 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return sp; 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char* storage = Reserve(sp.size(), block_buffer_idx); 12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(storage, sp.data(), sp.size()); 12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return base::StringPiece(storage, sp.size()); 12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenchar* BalsaBuffer::Reserve(size_t size, 13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Blocks::size_type* block_buffer_idx) { 13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // There should always be a 'first_block', even if it 13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // contains nothing. 13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_GE(blocks_.size(), 1u); 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BufferBlock* block = NULL; 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0; 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (; block_idx < blocks_.size(); ++block_idx) { 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (blocks_[block_idx].bytes_free >= size) { 14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen block = &blocks_[block_idx]; 14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (block == NULL) { 14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (blocksize_ < size) { 14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.push_back(AllocCustomBlock(size)); 14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.push_back(AllocBlock()); 14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen block = &blocks_.back(); 15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char* storage = block->start_of_unused_bytes(); 15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen block->bytes_free -= size; 15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (block_buffer_idx) { 15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *block_buffer_idx = block_idx; 15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return storage; 15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BalsaBuffer::Clear() { 16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHECK(!blocks_.empty()); 16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (blocksize_ == blocks_[0].buffer_size) { 16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CleanupBlocksStartingFrom(1); 16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[0].bytes_free = blocks_[0].buffer_size; 16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CleanupBlocksStartingFrom(0); 16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.push_back(AllocBlock()); 16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_GE(blocks_.size(), 1u); 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen can_write_to_contiguous_buffer_ = true; 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BalsaBuffer::Swap(BalsaBuffer* b) { 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.swap(b->blocks_); 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::swap(can_write_to_contiguous_buffer_, 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen b->can_write_to_contiguous_buffer_); 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::swap(blocksize_, b->blocksize_); 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BalsaBuffer::CopyFrom(const BalsaBuffer& b) { 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CleanupBlocksStartingFrom(0); 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.resize(b.blocks_.size()); 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (Blocks::size_type i = 0; i < blocks_.size(); ++i) { 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_[i] = CopyBlock(b.blocks_[i]); 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocksize_ = b.blocksize_; 18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_; 18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaBuffer::BalsaBuffer() 19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) { 19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.push_back(AllocBlock()); 19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaBuffer::BalsaBuffer(size_t blocksize) : 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocksize_(blocksize), can_write_to_contiguous_buffer_(true) { 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.push_back(AllocBlock()); 19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaBuffer::BufferBlock BalsaBuffer::AllocBlock() { 20272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return AllocCustomBlock(blocksize_); 20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaBuffer::BufferBlock BalsaBuffer::AllocCustomBlock(size_t blocksize) { 20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return BufferBlock(new char[blocksize], blocksize, blocksize); 20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 20872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaBuffer::BufferBlock BalsaBuffer::CopyBlock(const BufferBlock& b) { 21072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BufferBlock block = b; 21172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (b.buffer == NULL) { 21272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return block; 21372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 21472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen block.buffer = new char[b.buffer_size]; 21672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(block.buffer, b.buffer, b.bytes_used()); 21772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return block; 21872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 21972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 22072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid BalsaBuffer::CleanupBlocksStartingFrom(Blocks::size_type start_idx) { 22172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (Blocks::size_type i = start_idx; i < blocks_.size(); ++i) { 22272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete[] blocks_[i].buffer; 22372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen blocks_.resize(start_idx); 22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaHeaders::BalsaHeaders() 22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : balsa_buffer_(4096), 22972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen content_length_(0), 23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH), 23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parsed_response_code_(0), 23272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen firstline_buffer_base_idx_(0), 23372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen whitespace_1_idx_(0), 23472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen non_whitespace_1_idx_(0), 23572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen whitespace_2_idx_(0), 23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen non_whitespace_2_idx_(0), 23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen whitespace_3_idx_(0), 23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen non_whitespace_3_idx_(0), 23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen whitespace_4_idx_(0), 24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen end_of_firstline_idx_(0), 24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen transfer_encoding_is_chunked_(false) { 24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenBalsaHeaders::~BalsaHeaders() {} 24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::Clear() { 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott balsa_buffer_.Clear(); 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transfer_encoding_is_chunked_ = false; 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_ = 0; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_response_code_ = 0; 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott firstline_buffer_base_idx_ = 0; 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_1_idx_ = 0; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_1_idx_ = 0; 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_2_idx_ = 0; 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_2_idx_ = 0; 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_3_idx_ = 0; 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_3_idx_ = 0; 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_4_idx_ = 0; 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_of_firstline_idx_ = 0; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_lines_.clear(); 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::Swap(BalsaHeaders* other) { 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Protect against swapping with self. 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (this == other) return; 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott balsa_buffer_.Swap(&other->balsa_buffer_); 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool tmp_bool = transfer_encoding_is_chunked_; 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transfer_encoding_is_chunked_ = other->transfer_encoding_is_chunked_; 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->transfer_encoding_is_chunked_ = tmp_bool; 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t tmp_size_t = content_length_; 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_ = other->content_length_; 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->content_length_ = tmp_size_t; 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeadersEnums::ContentLengthStatus tmp_status = 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_status_; 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_status_ = other->content_length_status_; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->content_length_status_ = tmp_status; 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = parsed_response_code_; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_response_code_ = other->parsed_response_code_; 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->parsed_response_code_ = tmp_size_t; 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaBuffer::Blocks::size_type tmp_blk_idx = firstline_buffer_base_idx_; 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott firstline_buffer_base_idx_ = other->firstline_buffer_base_idx_; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->firstline_buffer_base_idx_ = tmp_blk_idx; 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = whitespace_1_idx_; 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_1_idx_ = other->whitespace_1_idx_; 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->whitespace_1_idx_ = tmp_size_t; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = non_whitespace_1_idx_; 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_1_idx_ = other->non_whitespace_1_idx_; 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->non_whitespace_1_idx_ = tmp_size_t; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = whitespace_2_idx_; 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_2_idx_ = other->whitespace_2_idx_; 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->whitespace_2_idx_ = tmp_size_t; 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = non_whitespace_2_idx_; 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_2_idx_ = other->non_whitespace_2_idx_; 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->non_whitespace_2_idx_ = tmp_size_t; 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = whitespace_3_idx_; 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_3_idx_ = other->whitespace_3_idx_; 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->whitespace_3_idx_ = tmp_size_t; 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = non_whitespace_3_idx_; 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_3_idx_ = other->non_whitespace_3_idx_; 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->non_whitespace_3_idx_ = tmp_size_t; 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = whitespace_4_idx_; 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_4_idx_ = other->whitespace_4_idx_; 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->whitespace_4_idx_ = tmp_size_t; 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_size_t = end_of_firstline_idx_; 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_of_firstline_idx_ = other->end_of_firstline_idx_; 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other->end_of_firstline_idx_ = tmp_size_t; 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott swap(header_lines_, other->header_lines_); 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::CopyFrom(const BalsaHeaders& other) { 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Protect against copying with self. 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (this == &other) return; 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott balsa_buffer_.CopyFrom(other.balsa_buffer_); 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transfer_encoding_is_chunked_ = other.transfer_encoding_is_chunked_; 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_ = other.content_length_; 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_status_ = other.content_length_status_; 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_response_code_ = other.parsed_response_code_; 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott firstline_buffer_base_idx_ = other.firstline_buffer_base_idx_; 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_1_idx_ = other.whitespace_1_idx_; 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_1_idx_ = other.non_whitespace_1_idx_; 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_2_idx_ = other.whitespace_2_idx_; 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_2_idx_ = other.non_whitespace_2_idx_; 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_3_idx_ = other.whitespace_3_idx_; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_3_idx_ = other.non_whitespace_3_idx_; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_4_idx_ = other.whitespace_4_idx_; 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_of_firstline_idx_ = other.end_of_firstline_idx_; 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_lines_ = other.header_lines_; 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::AddAndMakeDescription(const base::StringPiece& key, 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value, 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLineDescription* d) { 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(d != NULL); 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // + 2 to size for ": " 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t line_size = key.size() + 2 + value.size(); 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaBuffer::Blocks::size_type block_buffer_idx = 0; 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* storage = balsa_buffer_.Reserve(line_size, &block_buffer_idx); 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t base_idx = storage - GetPtr(block_buffer_idx); 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* cur_loc = storage; 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, key.data(), key.size()); 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cur_loc += key.size(); 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ':'; 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ' '; 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, value.data(), value.size()); 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *d = HeaderLineDescription(base_idx, 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_idx + key.size(), 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_idx + key.size() + 2, 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_idx + key.size() + 2 + value.size(), 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block_buffer_idx); 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::AppendOrPrependAndMakeDescription( 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key, 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value, 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool append, 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLineDescription* d) { 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Figure out how much space we need to reserve for the new header size. 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t old_value_size = d->last_char_idx - d->value_begin_idx; 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (old_value_size == 0) { 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddAndMakeDescription(key, value, d); 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::StringPiece old_value(GetPtr(d->buffer_base_idx) + d->value_begin_idx, 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott old_value_size); 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaBuffer::Blocks::size_type block_buffer_idx = 0; 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // + 3 because we potentially need to add ": ", and "," to the line. 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t new_size = key.size() + 3 + old_value_size + value.size(); 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* storage = balsa_buffer_.Reserve(new_size, &block_buffer_idx); 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t base_idx = storage - GetPtr(block_buffer_idx); 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::StringPiece first_value = old_value; 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::StringPiece second_value = value; 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!append) { // !append == prepend 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott first_value = value; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott second_value = old_value; 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* cur_loc = storage; 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, key.data(), key.size()); 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cur_loc += key.size(); 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ':'; 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ' '; 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, first_value.data(), first_value.size()); 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cur_loc += first_value.size(); 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ','; 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, second_value.data(), second_value.size()); 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *d = HeaderLineDescription(base_idx, 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_idx + key.size(), 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_idx + key.size() + 2, 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base_idx + new_size, 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott block_buffer_idx); 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Removes all keys value pairs with key 'key' starting at 'start'. 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::RemoveAllOfHeaderStartingAt(const base::StringPiece& key, 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::iterator start) { 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (start != header_lines_.end()) { 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott start->skip = true; 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++start; 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott start = GetHeaderLinesIterator(key, start); 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::HackHeader(const base::StringPiece& key, 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value) { 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See TODO in balsa_headers.h 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator end = header_lines_.end(); 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator begin = header_lines_.begin(); 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::iterator i = GetHeaderLinesIteratorNoSkip(key, begin); 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i != end) { 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // First, remove all of the header lines including this one. We want to 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // remove before replacing, in case our replacement ends up being appended 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // at the end (and thus would be removed by this call) 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeaderStartingAt(key, i); 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now add the replacement, at this location. 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddAndMakeDescription(key, value, &(*i)); 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHeader(key, value); 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::HackAppendToHeader(const base::StringPiece& key, 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& append_value) { 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // See TODO in balsa_headers.h 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator end = header_lines_.end(); 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator begin = header_lines_.begin(); 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::iterator i = GetHeaderLinesIterator(key, begin); 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == end) { 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HackHeader(key, append_value); 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendOrPrependAndMakeDescription(key, append_value, true, &(*i)); 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::ReplaceOrAppendHeader(const base::StringPiece& key, 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value) { 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator end = header_lines_.end(); 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator begin = header_lines_.begin(); 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::iterator i = GetHeaderLinesIterator(key, begin); 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i != end) { 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // First, remove all of the header lines including this one. We want to 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // remove before replacing, in case our replacement ends up being appended 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // at the end (and thus would be removed by this call) 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeaderStartingAt(key, i); 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now, take the first instance and replace it. This will remove the 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 'skipped' tag if the replacement is done in-place. 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddAndMakeDescription(key, value, &(*i)); 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHeader(key, value); 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::AppendHeader(const base::StringPiece& key, 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value) { 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLineDescription hld; 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddAndMakeDescription(key, value, &hld); 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_lines_.push_back(hld); 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::AppendToHeader(const base::StringPiece& key, 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value) { 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendOrPrependToHeader(key, value, true); 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::PrependToHeader(const base::StringPiece& key, 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value) { 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendOrPrependToHeader(key, value, false); 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbase::StringPiece BalsaHeaders::GetValueFromHeaderLineDescription( 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLineDescription& line) const { 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(line.last_char_idx, line.value_begin_idx); 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return base::StringPiece(GetPtr(line.buffer_base_idx) + line.value_begin_idx, 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott line.last_char_idx - line.value_begin_idx); 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst base::StringPiece BalsaHeaders::GetHeader( 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key) const { 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!IsMultivaluedHeader(key)) 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "Header '" << key << "' may consist of multiple lines. Do not " 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "use BalsaHeaders::GetHeader() or you may be missing some of its " 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "values."; 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::const_iterator end = header_lines_.end(); 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::const_iterator begin = header_lines_.begin(); 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::const_iterator i = GetConstHeaderLinesIterator(key, begin); 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == end) { 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return base::StringPiece(NULL, 0); 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GetValueFromHeaderLineDescription(*i); 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBalsaHeaders::const_header_lines_iterator BalsaHeaders::GetHeaderPosition( 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key) const { 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::const_iterator end = header_lines_.end(); 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::const_iterator begin = header_lines_.begin(); 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::const_iterator i = GetConstHeaderLinesIterator(key, begin); 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == end) { 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return header_lines_end(); 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return const_header_lines_iterator(this, (i - begin)); 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBalsaHeaders::const_header_lines_key_iterator BalsaHeaders::GetIteratorForKey( 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key) const { 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::const_iterator i = 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetConstHeaderLinesIterator(key, header_lines_.begin()); 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == header_lines_.end()) { 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return header_lines_key_end(); 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::const_iterator begin = header_lines_.begin(); 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return const_header_lines_key_iterator(this, (i - begin), key); 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::AppendOrPrependToHeader(const base::StringPiece& key, 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& value, 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool append) { 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::iterator i = GetHeaderLinesIterator(key, header_lines_.begin()); 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == header_lines_.end()) { 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The header did not exist already. Instead of appending to an existing 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // header simply append the key/value pair to the headers. 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHeader(key, value); 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLineDescription hld = *i; 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendOrPrependAndMakeDescription(key, value, append, &hld); 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Invalidate the old header line and add the new one. 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i->skip = true; 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_lines_.push_back(hld); 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBalsaHeaders::HeaderLines::const_iterator 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBalsaHeaders::GetConstHeaderLinesIterator( 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key, 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders::HeaderLines::const_iterator start) const { 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::const_iterator end = header_lines_.end(); 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (HeaderLines::const_iterator i = start; i != end; ++i) { 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLineDescription& line = *i; 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (line.skip) { 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const size_t key_len = line.key_end_idx - line.first_char_idx; 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key_len != key.size()) { 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott key.data(), key_len) == 0) { 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(line.last_char_idx, line.value_begin_idx); 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return i; 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return end; 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIteratorNoSkip( 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key, 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders::HeaderLines::iterator start) { 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator end = header_lines_.end(); 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (HeaderLines::iterator i = start; i != end; ++i) { 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLineDescription& line = *i; 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const size_t key_len = line.key_end_idx - line.first_char_idx; 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key_len != key.size()) { 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott key.data(), key_len) == 0) { 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(line.last_char_idx, line.value_begin_idx); 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return i; 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return end; 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottBalsaHeaders::HeaderLines::iterator BalsaHeaders::GetHeaderLinesIterator( 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key, 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders::HeaderLines::iterator start) { 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::iterator end = header_lines_.end(); 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (HeaderLines::iterator i = start; i != end; ++i) { 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLineDescription& line = *i; 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (line.skip) { 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const size_t key_len = line.key_end_idx - line.first_char_idx; 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key_len != key.size()) { 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott key.data(), key_len) == 0) { 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(line.last_char_idx, line.value_begin_idx); 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return i; 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return end; 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::GetAllOfHeader( 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& key, std::vector<base::StringPiece>* out) const { 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (const_header_lines_key_iterator it = GetIteratorForKey(key); 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott it != header_lines_end(); ++it) { 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott out->push_back(it->second); 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BalsaHeaders::HasNonEmptyHeader(const base::StringPiece& key) const { 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (const_header_lines_key_iterator it = GetIteratorForKey(key); 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott it != header_lines_key_end(); ++it) { 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!it->second.empty()) 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::GetAllOfHeaderAsString(const base::StringPiece& key, 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* out) const { 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const_header_lines_iterator it = header_lines_begin(); 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const_header_lines_iterator end = header_lines_end(); 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; it != end; ++it) { 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key == it->first) { 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!out->empty()) { 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott out->append(","); 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott out->append(std::string(it->second.data(), it->second.size())); 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool BalsaHeaders::IsMultivaluedHeader(const base::StringPiece& header) { 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return g_multivalued_headers.find(header) != g_multivalued_headers.end(); 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::RemoveAllOfHeader(const base::StringPiece& key) { 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLines::iterator it = GetHeaderLinesIterator(key, header_lines_.begin()); 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeaderStartingAt(key, it); 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::RemoveAllHeadersWithPrefix(const base::StringPiece& key) { 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (HeaderLines::size_type i = 0; i < header_lines_.size(); ++i) { 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (header_lines_[i].skip) { 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderLineDescription& line = header_lines_[i]; 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const size_t key_len = line.key_end_idx - line.first_char_idx; 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (key_len < key.size()) { 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the key given to us is longer than this header, don't consider it. 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!strncasecmp(GetPtr(line.buffer_base_idx) + line.first_char_idx, 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott key.data(), key.size())) { 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott line.skip = true; 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t BalsaHeaders::GetMemoryUsedLowerBound() const { 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (sizeof(*this) + 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott balsa_buffer_.GetTotalBufferBlockSize() + 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header_lines_.capacity() * sizeof(HeaderLineDescription)); 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t BalsaHeaders::GetSizeForWriteBuffer() const { 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // First add the space required for the first line + CRLF 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t write_buf_size = whitespace_4_idx_ - non_whitespace_1_idx_ + 2; 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Then add the space needed for each header line to write out + CRLF. 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLines::size_type end = header_lines_.size(); 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (HeaderLines::size_type i = 0; i < end; ++i) { 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderLineDescription& line = header_lines_[i]; 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!line.skip) { 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add the key size and ": ". 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_size += line.key_end_idx - line.first_char_idx + 2; 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add the value size and the CRLF 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_buf_size += line.last_char_idx - line.value_begin_idx + 2; 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Finally tag on the terminal CRLF. 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return write_buf_size + 2; 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::DumpToString(std::string* str) const { 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece firstline = first_line(); 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int buffer_length = 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OriginalHeaderStreamEnd() - OriginalHeaderStreamBegin(); 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // First check whether the header object is empty. 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (firstline.empty() && buffer_length == 0) { 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott str->append("\n<empty header>\n"); 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Then check whether the header is in a partially parsed state. If so, just 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // dump the raw data. 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (balsa_buffer_.can_write_to_contiguous_buffer()) { 7254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(str, "\n<incomplete header len: %d>\n%.*s\n", 7264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch buffer_length, buffer_length, 7274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch OriginalHeaderStreamBegin()); 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the header is complete, then just dump them with the logical key value 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // pair. 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott str->reserve(str->size() + GetSizeForWriteBuffer()); 7344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(str, "\n %.*s\n", 7354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch static_cast<int>(firstline.size()), 7364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch firstline.data()); 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BalsaHeaders::const_header_lines_iterator i = header_lines_begin(); 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; i != header_lines_end(); ++i) { 7394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch base::StringAppendF(str, " %.*s: %.*s\n", 7404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch static_cast<int>(i->first.size()), i->first.data(), 7414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch static_cast<int>(i->second.size()), i->second.data()); 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetFirstLine(const base::StringPiece& line) { 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::StringPiece new_line = balsa_buffer_.Write(line, 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &firstline_buffer_base_idx_); 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_1_idx_ = new_line.data() - GetPtr(firstline_buffer_base_idx_); 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_1_idx_ = whitespace_1_idx_; 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_4_idx_ = whitespace_1_idx_ + line.size(); 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_2_idx_ = whitespace_4_idx_; 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_2_idx_ = whitespace_4_idx_; 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_3_idx_ = whitespace_4_idx_; 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_3_idx_ = whitespace_4_idx_; 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_of_firstline_idx_ = whitespace_4_idx_; 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetContentLength(size_t length) { 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the content-length is already the one we want, don't do anything. 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_length_status_ == BalsaHeadersEnums::VALID_CONTENT_LENGTH && 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_ == length) { 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece content_length(kContentLength, 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(kContentLength) - 1); 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If header state indicates that there is either a content length or 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // transfer encoding header, remove them before adding the new content 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // length. There is always the possibility that client can manually add 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // either header directly and cause content_length_status_ or 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // transfer_encoding_is_chunked_ to be inconsistent with the actual header. 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // In the interest of efficiency, however, we will assume that clients will 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // use the header object correctly and thus we will not scan the all headers 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // each time this function is called. 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH) { 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeader(content_length); 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (transfer_encoding_is_chunked_) { 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece transfer_encoding(kTransferEncoding, 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(kTransferEncoding) - 1); 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeader(transfer_encoding); 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transfer_encoding_is_chunked_ = false; 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_status_ = BalsaHeadersEnums::VALID_CONTENT_LENGTH; 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_ = length; 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // FastUInt64ToBuffer is supposed to use a maximum of kFastToBufferSize bytes. 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buffer[kFastToBufferSize]; 786201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int len_converted = snprintf(buffer, sizeof(buffer), "%zd", length); 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK_GT(len_converted, 0); 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece length_str(buffer, len_converted); 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHeader(content_length, length_str); 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetChunkEncoding(bool chunk_encode) { 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (transfer_encoding_is_chunked_ == chunk_encode) { 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_length_status_ != BalsaHeadersEnums::NO_CONTENT_LENGTH && 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott chunk_encode) { 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Want to change to chunk encoding, but have content length. Arguably we 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // can leave this step out, since transfer-encoding overrides 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // content-length. 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece content_length(kContentLength, 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(kContentLength) - 1); 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeader(content_length); 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH; 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_length_ = 0; 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece transfer_encoding(kTransferEncoding, 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(kTransferEncoding) - 1); 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (chunk_encode) { 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char kChunked[] = "chunked"; 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece chunked(kChunked, sizeof(kChunked) - 1); 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AppendHeader(transfer_encoding, chunked); 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveAllOfHeader(transfer_encoding); 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transfer_encoding_is_chunked_ = chunk_encode; 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See the comment about this function in the header file for a 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// warning about its usage. 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetFirstlineFromStringPieces( 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& firstline_a, 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& firstline_b, 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const base::StringPiece& firstline_c) { 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t line_size = (firstline_a.size() + 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott firstline_b.size() + 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott firstline_c.size() + 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 2); 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* storage = balsa_buffer_.Reserve(line_size, &firstline_buffer_base_idx_); 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* cur_loc = storage; 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, firstline_a.data(), firstline_a.size()); 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cur_loc += firstline_a.size(); 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ' '; 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, firstline_b.data(), firstline_b.size()); 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cur_loc += firstline_b.size(); 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *cur_loc = ' '; 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++cur_loc; 843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(cur_loc, firstline_c.data(), firstline_c.size()); 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_1_idx_ = storage - GetPtr(firstline_buffer_base_idx_); 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_1_idx_ = whitespace_1_idx_; 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_2_idx_ = non_whitespace_1_idx_ + firstline_a.size(); 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_2_idx_ = whitespace_2_idx_ + 1; 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_3_idx_ = non_whitespace_2_idx_ + firstline_b.size(); 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_3_idx_ = whitespace_3_idx_ + 1; 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_4_idx_ = non_whitespace_3_idx_ + firstline_c.size(); 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end_of_firstline_idx_ = whitespace_4_idx_; 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetRequestMethod(const base::StringPiece& method) { 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is the first of the three parts of the firstline. 858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (method.size() <= (whitespace_2_idx_ - non_whitespace_1_idx_)) { 859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_1_idx_ = whitespace_2_idx_ - method.size(); 860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* stream_begin = GetPtr(firstline_buffer_base_idx_); 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(stream_begin + non_whitespace_1_idx_, 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott method.data(), 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott method.size()); 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The new method is too large to fit in the space available for the old 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // one, so we have to reformat the firstline. 867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetFirstlineFromStringPieces(method, request_uri(), request_version()); 868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetResponseVersion(const base::StringPiece& version) { 872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: There is no difference between request_method() and 873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // response_Version(). Thus, a function to set one is equivalent to a 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // function to set the other. We maintain two functions for this as it is 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // much more descriptive, and makes code more understandable. 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetRequestMethod(version); 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetRequestUri(const base::StringPiece& uri) { 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetFirstlineFromStringPieces(request_method(), uri, request_version()); 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetResponseCode(const base::StringPiece& code) { 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: There is no difference between request_uri() and response_code(). 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Thus, a function to set one is equivalent to a function to set the other. 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We maintain two functions for this as it is much more descriptive, and 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // makes code more understandable. 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetRequestUri(code); 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetParsedResponseCodeAndUpdateFirstline( 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t parsed_response_code) { 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buffer[kFastToBufferSize]; 894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len_converted = snprintf(buffer, sizeof(buffer), 895201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch "%zd", parsed_response_code); 896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK_GT(len_converted, 0); 897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetResponseCode(base::StringPiece(buffer, len_converted)); 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetRequestVersion(const base::StringPiece& version) { 901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This is the last of the three parts of the firstline. 902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since whitespace_3_idx and non_whitespace_3_idx may point to the same 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // place, we ensure below that any available space includes space for a 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // litteral space (' ') character between the second component and the third 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // component. If the space between whitespace_3_idx_ and 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // end_of_firstline_idx_ is >= to version.size() + 1 (for the space), then we 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // can update the firstline in-place. 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* stream_begin = GetPtr(firstline_buffer_base_idx_); 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (version.size() + 1 <= end_of_firstline_idx_ - whitespace_3_idx_) { 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *(stream_begin + whitespace_3_idx_) = kSpaceChar; 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott non_whitespace_3_idx_ = whitespace_3_idx_ + 1; 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott whitespace_4_idx_ = non_whitespace_3_idx_ + version.size(); 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(stream_begin + non_whitespace_3_idx_, 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott version.data(), 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott version.size()); 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The new version is to large to fit in the space available for the old 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // one, so we have to reformat the firstline. 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetFirstlineFromStringPieces(request_method(), request_uri(), version); 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid BalsaHeaders::SetResponseReasonPhrase(const base::StringPiece& reason) { 924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: There is no difference between request_version() and 925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // response_reason_phrase(). Thus, a function to set one is equivalent to a 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // function to set the other. We maintain two functions for this as it is 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // much more descriptive, and makes code more understandable. 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetRequestVersion(reason); 929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 932