Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: net/tools/quic/spdy_balsa_utils.cc

Issue 1357953002: Replace the existing SpdyHeaderBlock typedef with a class. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add NET_EXPORT to fix compile error on win_chromium_compile_dbg_ng. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/tools/quic/quic_spdy_server_stream_test.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "net/tools/quic/spdy_balsa_utils.h" 5 #include "net/tools/quic/spdy_balsa_utils.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/memory/scoped_ptr.h" 9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_piece.h" 11 #include "base/strings/string_piece.h"
12 #include "base/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "net/base/linked_hash_map.h"
13 #include "net/quic/quic_flags.h" 14 #include "net/quic/quic_flags.h"
14 #include "net/quic/spdy_utils.h" 15 #include "net/quic/spdy_utils.h"
15 #include "net/spdy/spdy_frame_builder.h" 16 #include "net/spdy/spdy_frame_builder.h"
16 #include "net/spdy/spdy_framer.h" 17 #include "net/spdy/spdy_framer.h"
17 #include "net/spdy/spdy_protocol.h" 18 #include "net/spdy/spdy_protocol.h"
18 #include "net/tools/balsa/balsa_headers.h" 19 #include "net/tools/balsa/balsa_headers.h"
19 #include "url/gurl.h" 20 #include "url/gurl.h"
20 21
21 using base::StringPiece; 22 using base::StringPiece;
22 using std::make_pair; 23 using std::make_pair;
23 using std::pair; 24 using std::pair;
24 using std::string; 25 using std::string;
25 26
26 namespace net { 27 namespace net {
27 namespace tools { 28 namespace tools {
28 namespace { 29 namespace {
29 30
30 const char kV4Host[] = ":authority"; 31 const char kV4Host[] = ":authority";
31 32
32 const char kV3Host[] = ":host"; 33 const char kV3Host[] = ":host";
33 const char kV3Path[] = ":path"; 34 const char kV3Path[] = ":path";
34 const char kV3Scheme[] = ":scheme"; 35 const char kV3Scheme[] = ":scheme";
35 const char kV3Method[] = ":method"; 36 const char kV3Method[] = ":method";
36 const char kV3Status[] = ":status"; 37 const char kV3Status[] = ":status";
37 const char kV3Version[] = ":version"; 38 const char kV3Version[] = ":version";
38 39
39 void PopulateSpdyHeaderBlock(const BalsaHeaders& headers, 40 void PopulateSpdyHeaderBlock(const BalsaHeaders& headers,
40 SpdyHeaderBlock* block, 41 SpdyHeaderBlock* block,
41 bool allow_empty_values) { 42 bool allow_empty_values) {
43 using HeaderValuesMap =
44 linked_hash_map<StringPiece, std::vector<StringPiece>>;
45 std::deque<string> names;
46 HeaderValuesMap header_values_map;
47 // First, gather references to all values for each name.
42 for (BalsaHeaders::const_header_lines_iterator hi = 48 for (BalsaHeaders::const_header_lines_iterator hi =
43 headers.header_lines_begin(); 49 headers.header_lines_begin();
44 hi != headers.header_lines_end(); ++hi) { 50 hi != headers.header_lines_end(); ++hi) {
45 if ((hi->second.length() == 0) && !allow_empty_values) { 51 if ((hi->second.length() == 0) && !allow_empty_values) {
46 DVLOG(1) << "Dropping empty header " << hi->first.as_string() 52 DVLOG(1) << "Dropping empty header " << hi->first.as_string()
47 << " from headers"; 53 << " from headers";
48 continue; 54 continue;
49 } 55 }
50 56 const string name = base::ToLowerASCII(hi->first.as_string());
51 // This unfortunately involves loads of copying, but its the simplest way 57 names.push_back(name);
52 // to sort the headers and leverage the framer. 58 header_values_map[name].push_back(hi->second);
53 string name = base::ToLowerASCII(hi->first.as_string()); 59 }
54 SpdyHeaderBlock::iterator it = block->find(name); 60 // Then, write joined representations to the header block.
55 if (it != block->end()) { 61 for (const auto& header : header_values_map) {
56 it->second.reserve(it->second.size() + 1 + hi->second.size()); 62 if (header.second.size() == 1) {
57 it->second.append("\0", 1); 63 // Avoid string allocation for the single value case.
58 it->second.append(hi->second.data(), hi->second.size()); 64 block->ReplaceOrAppendHeader(header.first, header.second[0]);
59 } else { 65 } else {
60 block->insert(make_pair(name, hi->second.as_string())); 66 StringPiece separator("\0", 1);
67 auto it = header.second.begin();
68 string value = it->as_string();
69 ++it;
70 for (; it != header.second.end(); ++it) {
71 separator.AppendToString(&value);
72 value.append(it->data(), it->size());
73 }
74 block->ReplaceOrAppendHeader(header.first, value);
61 } 75 }
62 } 76 }
63 } 77 }
64 78
65 void PopulateSpdy3RequestHeaderBlock(const BalsaHeaders& headers, 79 void PopulateSpdy3RequestHeaderBlock(const BalsaHeaders& headers,
66 const string& scheme, 80 const string& scheme,
67 const string& host_and_port, 81 const string& host_and_port,
68 const string& path, 82 const string& path,
69 SpdyHeaderBlock* block) { 83 SpdyHeaderBlock* block) {
70 PopulateSpdyHeaderBlock(headers, block, true); 84 PopulateSpdyHeaderBlock(headers, block, true);
71 StringPiece host_header = headers.GetHeader("Host"); 85 StringPiece host_header = headers.GetHeader("Host");
72 if (!host_header.empty()) { 86 if (!host_header.empty()) {
73 DCHECK(host_and_port.empty() || host_header == host_and_port); 87 DCHECK(host_and_port.empty() || host_header == host_and_port);
74 block->insert(make_pair(kV3Host, host_header.as_string())); 88 block->insert(make_pair(kV3Host, host_header));
75 } else { 89 } else {
76 block->insert(make_pair(kV3Host, host_and_port)); 90 block->insert(make_pair(kV3Host, host_and_port));
77 } 91 }
78 block->insert(make_pair(kV3Path, path)); 92 block->insert(make_pair(kV3Path, path));
79 block->insert(make_pair(kV3Scheme, scheme)); 93 block->insert(make_pair(kV3Scheme, scheme));
80 94
81 if (!headers.request_method().empty()) { 95 if (!headers.request_method().empty()) {
82 block->insert(make_pair(kV3Method, headers.request_method().as_string())); 96 block->insert(make_pair(kV3Method, headers.request_method()));
83 } 97 }
84 98
85 if (!headers.request_version().empty()) { 99 if (!headers.request_version().empty()) {
86 (*block)[kV3Version] = headers.request_version().as_string(); 100 (*block)[kV3Version] = headers.request_version();
87 } 101 }
88 } 102 }
89 103
90 void PopulateSpdy4RequestHeaderBlock(const BalsaHeaders& headers, 104 void PopulateSpdy4RequestHeaderBlock(const BalsaHeaders& headers,
91 const string& scheme, 105 const string& scheme,
92 const string& host_and_port, 106 const string& host_and_port,
93 const string& path, 107 const string& path,
94 SpdyHeaderBlock* block) { 108 SpdyHeaderBlock* block) {
95 PopulateSpdyHeaderBlock(headers, block, true); 109 PopulateSpdyHeaderBlock(headers, block, true);
96 StringPiece host_header = headers.GetHeader("Host"); 110 StringPiece host_header = headers.GetHeader("Host");
97 if (!host_header.empty()) { 111 if (!host_header.empty()) {
98 DCHECK(host_and_port.empty() || host_header == host_and_port); 112 DCHECK(host_and_port.empty() || host_header == host_and_port);
99 block->insert(make_pair(kV4Host, host_header.as_string())); 113 block->insert(make_pair(kV4Host, host_header));
100 // PopulateSpdyHeaderBlock already added the "host" header, 114 // PopulateSpdyHeaderBlock already added the "host" header,
101 // which is invalid for SPDY4. 115 // which is invalid for SPDY4.
102 block->erase("host"); 116 block->erase("host");
103 } else { 117 } else {
104 block->insert(make_pair(kV4Host, host_and_port)); 118 block->insert(make_pair(kV4Host, host_and_port));
105 } 119 }
106 block->insert(make_pair(kV3Path, path)); 120 block->insert(make_pair(kV3Path, path));
107 block->insert(make_pair(kV3Scheme, scheme)); 121 block->insert(make_pair(kV3Scheme, scheme));
108 122
109 if (!headers.request_method().empty()) { 123 if (!headers.request_method().empty()) {
110 block->insert(make_pair(kV3Method, headers.request_method().as_string())); 124 block->insert(make_pair(kV3Method, headers.request_method()));
111 } 125 }
112 } 126 }
113 127
114 void PopulateSpdyResponseHeaderBlock(SpdyMajorVersion version, 128 void PopulateSpdyResponseHeaderBlock(SpdyMajorVersion version,
115 const BalsaHeaders& headers, 129 const BalsaHeaders& headers,
116 SpdyHeaderBlock* block) { 130 SpdyHeaderBlock* block) {
117 if (version <= SPDY3) { 131 if (version <= SPDY3) {
118 string status = headers.response_code().as_string(); 132 string status = headers.response_code().as_string();
119 status.append(" "); 133 status.append(" ");
120 status.append(headers.response_reason_phrase().as_string()); 134 status.append(headers.response_reason_phrase().as_string());
121 (*block)[kV3Status] = status; 135 (*block)[kV3Status] = status;
122 (*block)[kV3Version] = headers.response_version().as_string(); 136 (*block)[kV3Version] = headers.response_version();
123 } else { 137 } else {
124 (*block)[kV3Status] = headers.response_code().as_string(); 138 (*block)[kV3Status] = headers.response_code();
125 } 139 }
126 140
127 PopulateSpdyHeaderBlock(headers, block, true); 141 PopulateSpdyHeaderBlock(headers, block, true);
128 } 142 }
129 143
130 bool IsSpecialSpdyHeader(SpdyHeaderBlock::const_iterator header, 144 bool IsSpecialSpdyHeader(SpdyHeaderBlock::const_iterator header,
131 BalsaHeaders* headers) { 145 BalsaHeaders* headers) {
132 if (header->first.empty() || header->second.empty()) { 146 return header->first.empty() || header->second.empty() ||
133 return true; 147 header->first[0] == ':';
134 }
135 const string& header_name = header->first;
136 return header_name.c_str()[0] == ':';
137 } 148 }
138 149
139 // The reason phrase should match regexp [\d\d\d [^\r\n]+]. If not, we will 150 // The reason phrase should match regexp [\d\d\d [^\r\n]+]. If not, we will
140 // fail to parse it. 151 // fail to parse it.
141 bool ParseReasonAndStatus(StringPiece status_and_reason, 152 bool ParseReasonAndStatus(StringPiece status_and_reason,
142 BalsaHeaders* headers, 153 BalsaHeaders* headers,
143 QuicVersion quic_version) { 154 QuicVersion quic_version) {
144 if (quic_version > QUIC_VERSION_24) { 155 if (quic_version > QUIC_VERSION_24) {
145 int status; 156 int status;
146 if (!base::StringToInt(status_and_reason, &status)) { 157 if (!base::StringToInt(status_and_reason, &status)) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 BlockIt host_it = header_block.find(kV3Host); 228 BlockIt host_it = header_block.find(kV3Host);
218 BlockIt method_it = header_block.find(kV3Method); 229 BlockIt method_it = header_block.find(kV3Method);
219 BlockIt path_it = header_block.find(kV3Path); 230 BlockIt path_it = header_block.find(kV3Path);
220 BlockIt scheme_it = header_block.find(kV3Scheme); 231 BlockIt scheme_it = header_block.find(kV3Scheme);
221 BlockIt end_it = header_block.end(); 232 BlockIt end_it = header_block.end();
222 233
223 string method; 234 string method;
224 if (method_it == end_it) { 235 if (method_it == end_it) {
225 method = "GET"; 236 method = "GET";
226 } else { 237 } else {
227 method = method_it->second; 238 method = method_it->second.as_string();
228 } 239 }
229 string uri; 240 string uri;
230 if (path_it == end_it) { 241 if (path_it == end_it) {
231 uri = "/"; 242 uri = "/";
232 } else { 243 } else {
233 uri = path_it->second; 244 uri = path_it->second.as_string();
234 } 245 }
235 request_headers->SetRequestFirstlineFromStringPieces( 246 request_headers->SetRequestFirstlineFromStringPieces(
236 method, uri, net::kHttp2VersionString); 247 method, uri, net::kHttp2VersionString);
237 248
238 if (scheme_it == end_it) { 249 if (scheme_it == end_it) {
239 request_headers->AppendHeader("Scheme", "https"); 250 request_headers->AppendHeader("Scheme", "https");
240 } else { 251 } else {
241 request_headers->AppendHeader("Scheme", scheme_it->second); 252 request_headers->AppendHeader("Scheme", scheme_it->second);
242 } 253 }
243 if (authority_it != end_it) { 254 if (authority_it != end_it) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 // static 350 // static
340 void SpdyBalsaUtils::SpdyHeadersToRequestHeaders(const SpdyHeaderBlock& block, 351 void SpdyBalsaUtils::SpdyHeadersToRequestHeaders(const SpdyHeaderBlock& block,
341 BalsaHeaders* headers, 352 BalsaHeaders* headers,
342 QuicVersion quic_version) { 353 QuicVersion quic_version) {
343 SpdyHeadersToBalsaHeaders(block, headers, quic_version, 354 SpdyHeadersToBalsaHeaders(block, headers, quic_version,
344 SpdyHeaderValidatorType::REQUEST); 355 SpdyHeaderValidatorType::REQUEST);
345 } 356 }
346 357
347 } // namespace tools 358 } // namespace tools
348 } // namespace net 359 } // namespace net
OLDNEW
« no previous file with comments | « net/tools/quic/quic_spdy_server_stream_test.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698