OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/hpack_header_table.h" | 5 #include "net/spdy/hpack_header_table.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "net/spdy/hpack_constants.h" | 10 #include "net/spdy/hpack_constants.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 STATIC_ENTRY("user-agent" , ""), // 58 | 92 STATIC_ENTRY("user-agent" , ""), // 58 |
93 STATIC_ENTRY("vary" , ""), // 59 | 93 STATIC_ENTRY("vary" , ""), // 59 |
94 STATIC_ENTRY("via" , ""), // 60 | 94 STATIC_ENTRY("via" , ""), // 60 |
95 STATIC_ENTRY("www-authenticate" , ""), // 61 | 95 STATIC_ENTRY("www-authenticate" , ""), // 61 |
96 }; | 96 }; |
97 | 97 |
98 #undef STATIC_ENTRY | 98 #undef STATIC_ENTRY |
99 | 99 |
100 } // namespace | 100 } // namespace |
101 | 101 |
| 102 bool HpackHeaderTable::EntryComparator::operator() ( |
| 103 const HpackEntry* lhs, const HpackEntry* rhs) const { |
| 104 int result = lhs->name().compare(rhs->name()); |
| 105 if (result != 0) |
| 106 return result < 0; |
| 107 result = lhs->value().compare(rhs->value()); |
| 108 if (result != 0) |
| 109 return result < 0; |
| 110 const size_t lhs_index = table_->IndexOf(lhs); |
| 111 const size_t rhs_index = table_->IndexOf(rhs); |
| 112 DCHECK(lhs == rhs || lhs_index != rhs_index) |
| 113 << "lhs: (" << lhs->name() << ", " << rhs->value() << ") rhs: (" |
| 114 << rhs->name() << ", " << rhs->value() << ")" |
| 115 << " lhs index: " << lhs_index << " rhs index: " << rhs_index; |
| 116 return lhs_index < rhs_index; |
| 117 } |
| 118 |
102 HpackHeaderTable::HpackHeaderTable() | 119 HpackHeaderTable::HpackHeaderTable() |
103 : settings_size_bound_(kDefaultHeaderTableSizeSetting), | 120 : index_(EntryComparator(this)), |
| 121 reference_set_(EntryComparator(this)), |
| 122 settings_size_bound_(kDefaultHeaderTableSizeSetting), |
104 size_(0), | 123 size_(0), |
105 max_size_(kDefaultHeaderTableSizeSetting), | 124 max_size_(kDefaultHeaderTableSizeSetting), |
106 total_insertions_(0), | 125 total_insertions_(0) { |
107 dynamic_entries_count_(0) { | |
108 for (const StaticEntry* it = kStaticTable; | 126 for (const StaticEntry* it = kStaticTable; |
109 it != kStaticTable + arraysize(kStaticTable); ++it) { | 127 it != kStaticTable + arraysize(kStaticTable); ++it) { |
110 static_entries_.push_back( | 128 static_entries_.push_back( |
111 HpackEntry(StringPiece(it->name, it->name_len), | 129 HpackEntry(StringPiece(it->name, it->name_len), |
112 StringPiece(it->value, it->value_len), | 130 StringPiece(it->value, it->value_len), |
113 true, // is_static | 131 true, // is_static |
114 total_insertions_, | 132 total_insertions_)); |
115 &dynamic_entries_count_)); | |
116 CHECK(index_.insert(&static_entries_.back()).second); | 133 CHECK(index_.insert(&static_entries_.back()).second); |
117 | 134 |
118 ++total_insertions_; | 135 ++total_insertions_; |
119 } | 136 } |
120 } | 137 } |
121 | 138 |
122 HpackHeaderTable::~HpackHeaderTable() {} | 139 HpackHeaderTable::~HpackHeaderTable() {} |
123 | 140 |
124 HpackEntry* HpackHeaderTable::GetByIndex(size_t index) { | 141 HpackEntry* HpackHeaderTable::GetByIndex(size_t index) { |
125 if (index == 0) { | 142 if (index == 0) { |
126 return NULL; | 143 return NULL; |
127 } | 144 } |
128 index -= 1; | 145 index -= 1; |
129 if (index < dynamic_entries_.size()) { | 146 if (index < dynamic_entries_.size()) { |
130 return &dynamic_entries_[index]; | 147 return &dynamic_entries_[index]; |
131 } | 148 } |
132 index -= dynamic_entries_.size(); | 149 index -= dynamic_entries_.size(); |
133 if (index < static_entries_.size()) { | 150 if (index < static_entries_.size()) { |
134 return &static_entries_[index]; | 151 return &static_entries_[index]; |
135 } | 152 } |
136 return NULL; | 153 return NULL; |
137 } | 154 } |
138 | 155 |
139 HpackEntry* HpackHeaderTable::GetByName(StringPiece name) { | 156 HpackEntry* HpackHeaderTable::GetByName(StringPiece name) { |
140 HpackEntry query(name, ""); | 157 HpackEntry query(name, ""); |
141 HpackEntry::OrderedSet::const_iterator it = index_.lower_bound(&query); | 158 OrderedEntrySet::const_iterator it = index_.lower_bound(&query); |
142 if (it != index_.end() && (*it)->name() == name) { | 159 if (it != index_.end() && (*it)->name() == name) { |
143 return *it; | 160 return *it; |
144 } | 161 } |
145 return NULL; | 162 return NULL; |
146 } | 163 } |
147 | 164 |
148 HpackEntry* HpackHeaderTable::GetByNameAndValue(StringPiece name, | 165 HpackEntry* HpackHeaderTable::GetByNameAndValue(StringPiece name, |
149 StringPiece value) { | 166 StringPiece value) { |
150 HpackEntry query(name, value); | 167 HpackEntry query(name, value); |
151 HpackEntry::OrderedSet::const_iterator it = index_.lower_bound(&query); | 168 OrderedEntrySet::const_iterator it = index_.lower_bound(&query); |
152 if (it != index_.end() && (*it)->name() == name && (*it)->value() == value) { | 169 if (it != index_.end() && (*it)->name() == name && (*it)->value() == value) { |
153 return *it; | 170 return *it; |
154 } | 171 } |
155 return NULL; | 172 return NULL; |
156 } | 173 } |
157 | 174 |
| 175 size_t HpackHeaderTable::IndexOf(const HpackEntry* entry) const { |
| 176 if (entry->IsLookup()) { |
| 177 return 0; |
| 178 } else if (entry->IsStatic()) { |
| 179 return 1 + entry->InsertionIndex() + dynamic_entries_.size(); |
| 180 } else { |
| 181 return total_insertions_ - entry->InsertionIndex(); |
| 182 } |
| 183 } |
| 184 |
158 void HpackHeaderTable::SetMaxSize(size_t max_size) { | 185 void HpackHeaderTable::SetMaxSize(size_t max_size) { |
159 CHECK_LE(max_size, settings_size_bound_); | 186 CHECK_LE(max_size, settings_size_bound_); |
160 | 187 |
161 max_size_ = max_size; | 188 max_size_ = max_size; |
162 if (size_ > max_size_) { | 189 if (size_ > max_size_) { |
163 Evict(EvictionCountToReclaim(size_ - max_size_)); | 190 Evict(EvictionCountToReclaim(size_ - max_size_)); |
164 CHECK_LE(size_, max_size_); | 191 CHECK_LE(size_, max_size_); |
165 } | 192 } |
166 } | 193 } |
167 | 194 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 | 231 |
205 void HpackHeaderTable::Evict(size_t count) { | 232 void HpackHeaderTable::Evict(size_t count) { |
206 for (size_t i = 0; i != count; ++i) { | 233 for (size_t i = 0; i != count; ++i) { |
207 CHECK(!dynamic_entries_.empty()); | 234 CHECK(!dynamic_entries_.empty()); |
208 HpackEntry* entry = &dynamic_entries_.back(); | 235 HpackEntry* entry = &dynamic_entries_.back(); |
209 | 236 |
210 size_ -= entry->Size(); | 237 size_ -= entry->Size(); |
211 CHECK_EQ(1u, index_.erase(entry)); | 238 CHECK_EQ(1u, index_.erase(entry)); |
212 reference_set_.erase(entry); | 239 reference_set_.erase(entry); |
213 dynamic_entries_.pop_back(); | 240 dynamic_entries_.pop_back(); |
214 | |
215 --dynamic_entries_count_; | |
216 DCHECK_EQ(dynamic_entries_count_, dynamic_entries_.size()); | |
217 } | 241 } |
218 } | 242 } |
219 | 243 |
220 HpackEntry* HpackHeaderTable::TryAddEntry(StringPiece name, StringPiece value) { | 244 HpackEntry* HpackHeaderTable::TryAddEntry(StringPiece name, StringPiece value) { |
221 Evict(EvictionCountForEntry(name, value)); | 245 Evict(EvictionCountForEntry(name, value)); |
222 | 246 |
223 size_t entry_size = HpackEntry::Size(name, value); | 247 size_t entry_size = HpackEntry::Size(name, value); |
224 if (entry_size > (max_size_ - size_)) { | 248 if (entry_size > (max_size_ - size_)) { |
225 // Entire table has been emptied, but there's still insufficient room. | 249 // Entire table has been emptied, but there's still insufficient room. |
226 DCHECK(dynamic_entries_.empty()); | 250 DCHECK(dynamic_entries_.empty()); |
227 DCHECK_EQ(0u, size_); | 251 DCHECK_EQ(0u, size_); |
228 return NULL; | 252 return NULL; |
229 } | 253 } |
230 dynamic_entries_.push_front(HpackEntry(name, | 254 dynamic_entries_.push_front(HpackEntry(name, |
231 value, | 255 value, |
232 false, // is_static | 256 false, // is_static |
233 total_insertions_, | 257 total_insertions_)); |
234 &total_insertions_)); | |
235 CHECK(index_.insert(&dynamic_entries_.front()).second); | 258 CHECK(index_.insert(&dynamic_entries_.front()).second); |
236 | 259 |
237 size_ += entry_size; | 260 size_ += entry_size; |
238 ++dynamic_entries_count_; | |
239 ++total_insertions_; | 261 ++total_insertions_; |
240 | 262 |
241 DCHECK_EQ(dynamic_entries_count_, dynamic_entries_.size()); | |
242 return &dynamic_entries_.front(); | 263 return &dynamic_entries_.front(); |
243 } | 264 } |
244 | 265 |
245 void HpackHeaderTable::ClearReferenceSet() { | 266 void HpackHeaderTable::ClearReferenceSet() { |
246 for (HpackEntry::OrderedSet::iterator it = reference_set_.begin(); | 267 for (OrderedEntrySet::iterator it = reference_set_.begin(); |
247 it != reference_set_.end(); ++it) { | 268 it != reference_set_.end(); ++it) { |
248 (*it)->set_state(0); | 269 (*it)->set_state(0); |
249 } | 270 } |
250 reference_set_.clear(); | 271 reference_set_.clear(); |
251 } | 272 } |
252 | 273 |
253 bool HpackHeaderTable::Toggle(HpackEntry* entry) { | 274 bool HpackHeaderTable::Toggle(HpackEntry* entry) { |
254 CHECK(!entry->IsStatic()); | 275 CHECK(!entry->IsStatic()); |
255 CHECK_EQ(0u, entry->state()); | 276 CHECK_EQ(0u, entry->state()); |
256 | 277 |
257 std::pair<HpackEntry::OrderedSet::iterator, bool> insert_result = | 278 std::pair<OrderedEntrySet::iterator, bool> insert_result = |
258 reference_set_.insert(entry); | 279 reference_set_.insert(entry); |
259 if (insert_result.second) { | 280 if (insert_result.second) { |
260 return true; | 281 return true; |
261 } else { | 282 } else { |
262 reference_set_.erase(insert_result.first); | 283 reference_set_.erase(insert_result.first); |
263 return false; | 284 return false; |
264 } | 285 } |
265 } | 286 } |
266 | 287 |
267 void HpackHeaderTable::DebugLogTableState() const { | 288 void HpackHeaderTable::DebugLogTableState() const { |
268 DVLOG(2) << "Reference Set:"; | 289 DVLOG(2) << "Reference Set:"; |
269 for (HpackEntry::OrderedSet::const_iterator it = reference_set_.begin(); | 290 for (OrderedEntrySet::const_iterator it = reference_set_.begin(); |
270 it != reference_set_.end(); ++it) { | 291 it != reference_set_.end(); ++it) { |
271 DVLOG(2) << " " << (*it)->GetDebugString(); | 292 DVLOG(2) << " " << (*it)->GetDebugString(); |
272 } | 293 } |
273 DVLOG(2) << "Dynamic table:"; | 294 DVLOG(2) << "Dynamic table:"; |
274 for (EntryTable::const_iterator it = dynamic_entries_.begin(); | 295 for (EntryTable::const_iterator it = dynamic_entries_.begin(); |
275 it != dynamic_entries_.end(); ++it) { | 296 it != dynamic_entries_.end(); ++it) { |
276 DVLOG(2) << " " << it->GetDebugString(); | 297 DVLOG(2) << " " << it->GetDebugString(); |
277 } | 298 } |
278 DVLOG(2) << "Full Index:"; | 299 DVLOG(2) << "Full Index:"; |
279 for (HpackEntry::OrderedSet::const_iterator it = index_.begin(); | 300 for (OrderedEntrySet::const_iterator it = index_.begin(); |
280 it != index_.end(); ++it) { | 301 it != index_.end(); ++it) { |
281 DVLOG(2) << " " << (*it)->GetDebugString(); | 302 DVLOG(2) << " " << (*it)->GetDebugString(); |
282 } | 303 } |
283 } | 304 } |
284 | 305 |
285 } // namespace net | 306 } // namespace net |
OLD | NEW |