| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #ifndef NET_SPDY_SPDY_HEADER_BLOCK_H_ | 5 #ifndef NET_SPDY_SPDY_HEADER_BLOCK_H_ |
| 6 #define NET_SPDY_SPDY_HEADER_BLOCK_H_ | 6 #define NET_SPDY_SPDY_HEADER_BLOCK_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <list> | 10 #include <list> |
| 11 #include <map> | 11 #include <map> |
| 12 #include <memory> | 12 #include <memory> |
| 13 #include <string> | 13 #include <string> |
| 14 #include <vector> |
| 14 | 15 |
| 15 #include "base/macros.h" | 16 #include "base/macros.h" |
| 16 #include "base/strings/string_piece.h" | 17 #include "base/strings/string_piece.h" |
| 17 #include "net/base/linked_hash_map.h" | 18 #include "net/base/linked_hash_map.h" |
| 18 #include "net/base/net_export.h" | 19 #include "net/base/net_export.h" |
| 19 #include "net/log/net_log.h" | 20 #include "net/log/net_log.h" |
| 20 | 21 |
| 21 namespace base { | 22 namespace base { |
| 22 class Value; | 23 class Value; |
| 23 } | 24 } |
| 24 | 25 |
| 25 namespace net { | 26 namespace net { |
| 26 | 27 |
| 27 class NetLogCaptureMode; | 28 class NetLogCaptureMode; |
| 28 | 29 |
| 29 namespace test { | 30 namespace test { |
| 31 class SpdyHeaderBlockPeer; |
| 30 class ValueProxyPeer; | 32 class ValueProxyPeer; |
| 31 } | 33 } |
| 32 | 34 |
| 33 // This class provides a key-value map that can be used to store SPDY header | 35 // This class provides a key-value map that can be used to store SPDY header |
| 34 // names and values. This data structure preserves insertion order. | 36 // names and values. This data structure preserves insertion order. |
| 35 // | 37 // |
| 36 // Under the hood, this data structure uses large, contiguous blocks of memory | 38 // Under the hood, this data structure uses large, contiguous blocks of memory |
| 37 // to store names and values. Lookups may be performed with StringPiece keys, | 39 // to store names and values. Lookups may be performed with StringPiece keys, |
| 38 // and values are returned as StringPieces (via ValueProxy, below). | 40 // and values are returned as StringPieces (via ValueProxy, below). |
| 39 // Value StringPieces are valid as long as the SpdyHeaderBlock exists; allocated | 41 // Value StringPieces are valid as long as the SpdyHeaderBlock exists; allocated |
| 40 // memory is never freed until SpdyHeaderBlock's destruction. | 42 // memory is never freed until SpdyHeaderBlock's destruction. |
| 41 // | 43 // |
| 42 // This implementation does not make much of an effort to minimize wasted space. | 44 // This implementation does not make much of an effort to minimize wasted space. |
| 43 // It's expected that keys are rarely deleted from a SpdyHeaderBlock. | 45 // It's expected that keys are rarely deleted from a SpdyHeaderBlock. |
| 44 class NET_EXPORT SpdyHeaderBlock { | 46 class NET_EXPORT SpdyHeaderBlock { |
| 45 private: | 47 private: |
| 46 using MapType = linked_hash_map<base::StringPiece, | |
| 47 base::StringPiece, | |
| 48 base::StringPieceHash>; | |
| 49 class Storage; | 48 class Storage; |
| 50 | 49 |
| 50 // Stores a list of value fragments that can be joined later with a |
| 51 // key-dependent separator. |
| 52 class NET_EXPORT HeaderValue { |
| 53 public: |
| 54 HeaderValue(Storage* storage, |
| 55 base::StringPiece key, |
| 56 base::StringPiece initial_value); |
| 57 |
| 58 // Moves are allowed. |
| 59 HeaderValue(HeaderValue&& other); |
| 60 HeaderValue& operator=(HeaderValue&& other); |
| 61 |
| 62 // Copies are not. |
| 63 HeaderValue(const HeaderValue& other) = delete; |
| 64 HeaderValue& operator=(const HeaderValue& other) = delete; |
| 65 |
| 66 ~HeaderValue(); |
| 67 |
| 68 // Consumes at most |fragment.size()| bytes of memory. |
| 69 void Append(base::StringPiece fragment); |
| 70 |
| 71 base::StringPiece value() const { return as_pair().second; } |
| 72 const std::pair<base::StringPiece, base::StringPiece>& as_pair() const; |
| 73 |
| 74 private: |
| 75 // May allocate a large contiguous region of memory to hold the concatenated |
| 76 // fragments and separators. |
| 77 base::StringPiece ConsolidatedValue() const; |
| 78 |
| 79 mutable Storage* storage_; |
| 80 mutable std::vector<base::StringPiece> fragments_; |
| 81 // The first element is the key; the second is the consolidated value. |
| 82 mutable std::pair<base::StringPiece, base::StringPiece> pair_; |
| 83 }; |
| 84 |
| 85 typedef linked_hash_map<base::StringPiece, HeaderValue, base::StringPieceHash> |
| 86 MapType; |
| 87 |
| 51 public: | 88 public: |
| 52 using iterator = MapType::iterator; | 89 typedef std::pair<base::StringPiece, base::StringPiece> value_type; |
| 53 using const_iterator = MapType::const_iterator; | 90 |
| 54 using value_type = MapType::value_type; | 91 // Provides iteration over a sequence of std::pair<StringPiece, StringPiece>, |
| 55 using reverse_iterator = MapType::reverse_iterator; | 92 // even though the underlying MapType::value_type is different. Dereferencing |
| 93 // the iterator will result in memory allocation for multi-value headers. |
| 94 class NET_EXPORT iterator { |
| 95 public: |
| 96 // The following type definitions fulfill the requirements for iterator |
| 97 // implementations. |
| 98 typedef std::pair<base::StringPiece, base::StringPiece> value_type; |
| 99 typedef value_type& reference; |
| 100 typedef value_type* pointer; |
| 101 typedef std::forward_iterator_tag iterator_category; |
| 102 typedef MapType::iterator::difference_type difference_type; |
| 103 |
| 104 // In practice, this iterator only offers access to const value_type. |
| 105 typedef const value_type& const_reference; |
| 106 typedef const value_type* const_pointer; |
| 107 |
| 108 explicit iterator(MapType::const_iterator it); |
| 109 iterator(const iterator& other); |
| 110 ~iterator(); |
| 111 |
| 112 // This will result in memory allocation if the value consists of multiple |
| 113 // fragments. |
| 114 const_reference operator*() const { return it_->second.as_pair(); } |
| 115 |
| 116 const_pointer operator->() const { return &(this->operator*()); } |
| 117 bool operator==(const iterator& it) const { return it_ == it.it_; } |
| 118 bool operator!=(const iterator& it) const { return !(*this == it); } |
| 119 |
| 120 iterator& operator++() { |
| 121 it_++; |
| 122 return *this; |
| 123 } |
| 124 |
| 125 iterator operator++(int) { |
| 126 auto ret = *this; |
| 127 this->operator++(); |
| 128 return ret; |
| 129 } |
| 130 |
| 131 private: |
| 132 MapType::const_iterator it_; |
| 133 }; |
| 134 typedef iterator const_iterator; |
| 56 | 135 |
| 57 class ValueProxy; | 136 class ValueProxy; |
| 58 | 137 |
| 59 SpdyHeaderBlock(); | 138 SpdyHeaderBlock(); |
| 60 SpdyHeaderBlock(const SpdyHeaderBlock& other) = delete; | 139 SpdyHeaderBlock(const SpdyHeaderBlock& other) = delete; |
| 61 SpdyHeaderBlock(SpdyHeaderBlock&& other); | 140 SpdyHeaderBlock(SpdyHeaderBlock&& other); |
| 62 ~SpdyHeaderBlock(); | 141 ~SpdyHeaderBlock(); |
| 63 | 142 |
| 64 SpdyHeaderBlock& operator=(const SpdyHeaderBlock& other) = delete; | 143 SpdyHeaderBlock& operator=(const SpdyHeaderBlock& other) = delete; |
| 65 SpdyHeaderBlock& operator=(SpdyHeaderBlock&& other); | 144 SpdyHeaderBlock& operator=(SpdyHeaderBlock&& other); |
| 66 SpdyHeaderBlock Clone() const; | 145 SpdyHeaderBlock Clone() const; |
| 67 | 146 |
| 68 bool operator==(const SpdyHeaderBlock& other) const; | 147 bool operator==(const SpdyHeaderBlock& other) const; |
| 69 bool operator!=(const SpdyHeaderBlock& other) const; | 148 bool operator!=(const SpdyHeaderBlock& other) const; |
| 70 | 149 |
| 71 // Provides a human readable multi-line representation of the stored header | 150 // Provides a human readable multi-line representation of the stored header |
| 72 // keys and values. | 151 // keys and values. |
| 73 std::string DebugString() const; | 152 std::string DebugString() const; |
| 74 | 153 |
| 75 // These methods delegate to our MapType member. | 154 iterator begin() { return iterator(block_.begin()); } |
| 76 iterator begin() { return block_.begin(); } | 155 iterator end() { return iterator(block_.end()); } |
| 77 iterator end() { return block_.end(); } | 156 const_iterator begin() const { return const_iterator(block_.begin()); } |
| 78 const_iterator begin() const { return block_.begin(); } | 157 const_iterator end() const { return const_iterator(block_.end()); } |
| 79 const_iterator end() const { return block_.end(); } | |
| 80 bool empty() const { return block_.empty(); } | 158 bool empty() const { return block_.empty(); } |
| 81 size_t size() const { return block_.size(); } | 159 size_t size() const { return block_.size(); } |
| 82 iterator find(base::StringPiece key) { return block_.find(key); } | 160 iterator find(base::StringPiece key) { return iterator(block_.find(key)); } |
| 83 const_iterator find(base::StringPiece key) const { return block_.find(key); } | 161 const_iterator find(base::StringPiece key) const { |
| 84 reverse_iterator rbegin() { return block_.rbegin(); } | 162 return const_iterator(block_.find(key)); |
| 163 } |
| 85 void erase(base::StringPiece key) { block_.erase(key); } | 164 void erase(base::StringPiece key) { block_.erase(key); } |
| 86 | 165 |
| 87 // Clears both our MapType member and the memory used to hold headers. | 166 // Clears both our MapType member and the memory used to hold headers. |
| 88 void clear(); | 167 void clear(); |
| 89 | 168 |
| 90 // The next few methods copy data into our backing storage. | 169 // The next few methods copy data into our backing storage. |
| 91 | 170 |
| 92 // If key already exists in the block, replaces the value of that key. Else | 171 // If key already exists in the block, replaces the value of that key. Else |
| 93 // adds a new header to the end of the block. | 172 // adds a new header to the end of the block. |
| 94 void insert(const MapType::value_type& value); | 173 void insert(const value_type& value); |
| 95 | 174 |
| 96 // If a header with the key is already present, then append the value to the | 175 // If a header with the key is already present, then append the value to the |
| 97 // existing header value, NUL ("\0") separated unless the key is cookie, in | 176 // existing header value, NUL ("\0") separated unless the key is cookie, in |
| 98 // which case the separator is "; ". | 177 // which case the separator is "; ". |
| 99 // If there is no such key, a new header with the key and value is added. | 178 // If there is no such key, a new header with the key and value is added. |
| 100 void AppendValueOrAddHeader(const base::StringPiece key, | 179 void AppendValueOrAddHeader(const base::StringPiece key, |
| 101 const base::StringPiece value); | 180 const base::StringPiece value); |
| 102 | 181 |
| 103 // Allows either lookup or mutation of the value associated with a key. | 182 // Allows either lookup or mutation of the value associated with a key. |
| 104 ValueProxy operator[](const base::StringPiece key); | 183 ValueProxy operator[](const base::StringPiece key); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 133 const base::StringPiece key); | 212 const base::StringPiece key); |
| 134 | 213 |
| 135 SpdyHeaderBlock::MapType* block_; | 214 SpdyHeaderBlock::MapType* block_; |
| 136 SpdyHeaderBlock::Storage* storage_; | 215 SpdyHeaderBlock::Storage* storage_; |
| 137 SpdyHeaderBlock::MapType::iterator lookup_result_; | 216 SpdyHeaderBlock::MapType::iterator lookup_result_; |
| 138 base::StringPiece key_; | 217 base::StringPiece key_; |
| 139 bool valid_; | 218 bool valid_; |
| 140 }; | 219 }; |
| 141 | 220 |
| 142 private: | 221 private: |
| 222 friend class test::SpdyHeaderBlockPeer; |
| 223 |
| 143 void AppendHeader(const base::StringPiece key, const base::StringPiece value); | 224 void AppendHeader(const base::StringPiece key, const base::StringPiece value); |
| 144 Storage* GetStorage(); | 225 Storage* GetStorage(); |
| 226 size_t bytes_allocated() const; |
| 145 | 227 |
| 146 // StringPieces held by |block_| point to memory owned by |*storage_|. | 228 // StringPieces held by |block_| point to memory owned by |*storage_|. |
| 147 // |storage_| might be nullptr as long as |block_| is empty. | 229 // |storage_| might be nullptr as long as |block_| is empty. |
| 148 MapType block_; | 230 MapType block_; |
| 149 std::unique_ptr<Storage> storage_; | 231 std::unique_ptr<Storage> storage_; |
| 150 }; | 232 }; |
| 151 | 233 |
| 234 // Writes |fragments| to |dst|, joined by |separator|. |dst| must be large |
| 235 // enough to hold the result. Returns the number of bytes written. |
| 236 NET_EXPORT size_t Join(char* dst, |
| 237 const std::vector<base::StringPiece>& fragments, |
| 238 base::StringPiece separator); |
| 239 |
| 152 // Converts a SpdyHeaderBlock into NetLog event parameters. | 240 // Converts a SpdyHeaderBlock into NetLog event parameters. |
| 153 NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback( | 241 NET_EXPORT std::unique_ptr<base::Value> SpdyHeaderBlockNetLogCallback( |
| 154 const SpdyHeaderBlock* headers, | 242 const SpdyHeaderBlock* headers, |
| 155 NetLogCaptureMode capture_mode); | 243 NetLogCaptureMode capture_mode); |
| 156 | 244 |
| 157 // Converts NetLog event parameters into a SPDY header block and writes them | 245 // Converts NetLog event parameters into a SPDY header block and writes them |
| 158 // to |headers|. |event_param| must have been created by | 246 // to |headers|. |event_param| must have been created by |
| 159 // SpdyHeaderBlockNetLogCallback. On failure, returns false and clears | 247 // SpdyHeaderBlockNetLogCallback. On failure, returns false and clears |
| 160 // |headers|. | 248 // |headers|. |
| 161 NET_EXPORT bool SpdyHeaderBlockFromNetLogParam( | 249 NET_EXPORT bool SpdyHeaderBlockFromNetLogParam( |
| 162 const base::Value* event_param, | 250 const base::Value* event_param, |
| 163 SpdyHeaderBlock* headers); | 251 SpdyHeaderBlock* headers); |
| 164 | 252 |
| 165 } // namespace net | 253 } // namespace net |
| 166 | 254 |
| 167 #endif // NET_SPDY_SPDY_HEADER_BLOCK_H_ | 255 #endif // NET_SPDY_SPDY_HEADER_BLOCK_H_ |
| OLD | NEW |