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 #include "net/tools/quic/spdy_utils.h" | 5 #include "net/tools/quic/spdy_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" |
(...skipping 16 matching lines...) Expand all Loading... |
27 const char* const kV3Path = ":path"; | 27 const char* const kV3Path = ":path"; |
28 const char* const kV3Scheme = ":scheme"; | 28 const char* const kV3Scheme = ":scheme"; |
29 const char* const kV3Status = ":status"; | 29 const char* const kV3Status = ":status"; |
30 const char* const kV3Method = ":method"; | 30 const char* const kV3Method = ":method"; |
31 const char* const kV3Version = ":version"; | 31 const char* const kV3Version = ":version"; |
32 | 32 |
33 void PopulateSpdyHeaderBlock(const BalsaHeaders& headers, | 33 void PopulateSpdyHeaderBlock(const BalsaHeaders& headers, |
34 SpdyHeaderBlock* block, | 34 SpdyHeaderBlock* block, |
35 bool allow_empty_values) { | 35 bool allow_empty_values) { |
36 for (BalsaHeaders::const_header_lines_iterator hi = | 36 for (BalsaHeaders::const_header_lines_iterator hi = |
37 headers.header_lines_begin(); | 37 headers.header_lines_begin(); |
38 hi != headers.header_lines_end(); | 38 hi != headers.header_lines_end(); |
39 ++hi) { | 39 ++hi) { |
40 if ((hi->second.length() == 0) && !allow_empty_values) { | 40 if ((hi->second.length() == 0) && !allow_empty_values) { |
41 DVLOG(1) << "Dropping empty header " << hi->first.as_string() | 41 DVLOG(1) << "Dropping empty header " << hi->first.as_string() |
42 << " from headers"; | 42 << " from headers"; |
43 continue; | 43 continue; |
44 } | 44 } |
45 | 45 |
46 // This unfortunately involves loads of copying, but its the simplest way | 46 // This unfortunately involves loads of copying, but its the simplest way |
47 // to sort the headers and leverage the framer. | 47 // to sort the headers and leverage the framer. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 (*block)[kV3Version] = headers.request_version().as_string(); | 82 (*block)[kV3Version] = headers.request_version().as_string(); |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 void PopulateSpdyResponseHeaderBlock(const BalsaHeaders& headers, | 86 void PopulateSpdyResponseHeaderBlock(const BalsaHeaders& headers, |
87 SpdyHeaderBlock* block) { | 87 SpdyHeaderBlock* block) { |
88 string status = headers.response_code().as_string(); | 88 string status = headers.response_code().as_string(); |
89 status.append(" "); | 89 status.append(" "); |
90 status.append(headers.response_reason_phrase().as_string()); | 90 status.append(headers.response_reason_phrase().as_string()); |
91 (*block)[kV3Status] = status; | 91 (*block)[kV3Status] = status; |
92 (*block)[kV3Version] = | 92 (*block)[kV3Version] = headers.response_version().as_string(); |
93 headers.response_version().as_string(); | |
94 | 93 |
95 // Empty header values are only allowed because this is spdy3. | 94 // Empty header values are only allowed because this is spdy3. |
96 PopulateSpdyHeaderBlock(headers, block, true); | 95 PopulateSpdyHeaderBlock(headers, block, true); |
97 } | 96 } |
98 | 97 |
99 // static | 98 // static |
100 SpdyHeaderBlock SpdyUtils::RequestHeadersToSpdyHeaders( | 99 SpdyHeaderBlock SpdyUtils::RequestHeadersToSpdyHeaders( |
101 const BalsaHeaders& request_headers) { | 100 const BalsaHeaders& request_headers) { |
102 string scheme; | 101 string scheme; |
103 string host_and_port; | 102 string host_and_port; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 // static | 157 // static |
159 string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) { | 158 string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) { |
160 int length = SpdyFramer::GetSerializedLength(SPDY3, &headers); | 159 int length = SpdyFramer::GetSerializedLength(SPDY3, &headers); |
161 SpdyFrameBuilder builder(length, SPDY3); | 160 SpdyFrameBuilder builder(length, SPDY3); |
162 SpdyFramer::WriteHeaderBlock(&builder, SPDY3, &headers); | 161 SpdyFramer::WriteHeaderBlock(&builder, SPDY3, &headers); |
163 scoped_ptr<SpdyFrame> block(builder.take()); | 162 scoped_ptr<SpdyFrame> block(builder.take()); |
164 return string(block->data(), length); | 163 return string(block->data(), length); |
165 } | 164 } |
166 | 165 |
167 bool IsSpecialSpdyHeader(SpdyHeaderBlock::const_iterator header, | 166 bool IsSpecialSpdyHeader(SpdyHeaderBlock::const_iterator header, |
168 BalsaHeaders* headers) { | 167 BalsaHeaders* headers) { |
169 if (header->first.empty() || header->second.empty()) { | 168 if (header->first.empty() || header->second.empty()) { |
170 return true; | 169 return true; |
171 } | 170 } |
172 const string& header_name = header->first; | 171 const string& header_name = header->first; |
173 return header_name.c_str()[0] == ':'; | 172 return header_name.c_str()[0] == ':'; |
174 } | 173 } |
175 | 174 |
176 bool SpdyUtils::FillBalsaRequestHeaders( | 175 bool SpdyUtils::FillBalsaRequestHeaders(const SpdyHeaderBlock& header_block, |
177 const SpdyHeaderBlock& header_block, | 176 BalsaHeaders* request_headers) { |
178 BalsaHeaders* request_headers) { | |
179 typedef SpdyHeaderBlock::const_iterator BlockIt; | 177 typedef SpdyHeaderBlock::const_iterator BlockIt; |
180 | 178 |
181 BlockIt host_it = header_block.find(kV3Host); | 179 BlockIt host_it = header_block.find(kV3Host); |
182 BlockIt path_it = header_block.find(kV3Path); | 180 BlockIt path_it = header_block.find(kV3Path); |
183 BlockIt scheme_it = header_block.find(kV3Scheme); | 181 BlockIt scheme_it = header_block.find(kV3Scheme); |
184 BlockIt method_it = header_block.find(kV3Method); | 182 BlockIt method_it = header_block.find(kV3Method); |
185 BlockIt end_it = header_block.end(); | 183 BlockIt end_it = header_block.end(); |
186 if (host_it == end_it || path_it == end_it || scheme_it == end_it || | 184 if (host_it == end_it || path_it == end_it || scheme_it == end_it || |
187 method_it == end_it) { | 185 method_it == end_it) { |
188 return false; | 186 return false; |
189 } | 187 } |
190 string url = scheme_it->second; | 188 string url = scheme_it->second; |
191 url.append("://"); | 189 url.append("://"); |
192 url.append(host_it->second); | 190 url.append(host_it->second); |
193 url.append(path_it->second); | 191 url.append(path_it->second); |
194 request_headers->SetRequestUri(url); | 192 request_headers->SetRequestUri(url); |
195 request_headers->SetRequestMethod(method_it->second); | 193 request_headers->SetRequestMethod(method_it->second); |
196 | 194 |
197 BlockIt cl_it = header_block.find("content-length"); | 195 BlockIt cl_it = header_block.find("content-length"); |
198 if (cl_it != header_block.end()) { | 196 if (cl_it != header_block.end()) { |
199 int content_length; | 197 int content_length; |
200 if (!base::StringToInt(cl_it->second, &content_length)) { | 198 if (!base::StringToInt(cl_it->second, &content_length)) { |
201 return false; | 199 return false; |
202 } | 200 } |
203 request_headers->SetContentLength(content_length); | 201 request_headers->SetContentLength(content_length); |
204 } | 202 } |
205 | 203 |
206 for (BlockIt it = header_block.begin(); it != header_block.end(); ++it) { | 204 for (BlockIt it = header_block.begin(); it != header_block.end(); ++it) { |
207 if (!IsSpecialSpdyHeader(it, request_headers)) { | 205 if (!IsSpecialSpdyHeader(it, request_headers)) { |
208 request_headers->AppendHeader(it->first, it->second); | 206 request_headers->AppendHeader(it->first, it->second); |
209 } | 207 } |
210 } | 208 } |
211 | 209 |
212 return true; | 210 return true; |
213 } | 211 } |
214 | 212 |
215 // The reason phrase should match regexp [\d\d\d [^\r\n]+]. If not, we will | 213 // The reason phrase should match regexp [\d\d\d [^\r\n]+]. If not, we will |
216 // fail to parse it. | 214 // fail to parse it. |
217 bool ParseReasonAndStatus(StringPiece status_and_reason, | 215 bool ParseReasonAndStatus(StringPiece status_and_reason, |
218 BalsaHeaders* headers) { | 216 BalsaHeaders* headers) { |
219 if (status_and_reason.size() < 5) | 217 if (status_and_reason.size() < 5) |
(...skipping 11 matching lines...) Expand all Loading... |
231 headers->SetResponseCode(status_str); | 229 headers->SetResponseCode(status_str); |
232 headers->set_parsed_response_code(status); | 230 headers->set_parsed_response_code(status); |
233 | 231 |
234 StringPiece reason(status_and_reason.data() + 4, | 232 StringPiece reason(status_and_reason.data() + 4, |
235 status_and_reason.length() - 4); | 233 status_and_reason.length() - 4); |
236 | 234 |
237 headers->SetResponseReasonPhrase(reason); | 235 headers->SetResponseReasonPhrase(reason); |
238 return true; | 236 return true; |
239 } | 237 } |
240 | 238 |
241 bool SpdyUtils::FillBalsaResponseHeaders( | 239 bool SpdyUtils::FillBalsaResponseHeaders(const SpdyHeaderBlock& header_block, |
242 const SpdyHeaderBlock& header_block, | 240 BalsaHeaders* request_headers) { |
243 BalsaHeaders* request_headers) { | |
244 typedef SpdyHeaderBlock::const_iterator BlockIt; | 241 typedef SpdyHeaderBlock::const_iterator BlockIt; |
245 | 242 |
246 BlockIt status_it = header_block.find(kV3Status); | 243 BlockIt status_it = header_block.find(kV3Status); |
247 BlockIt version_it = header_block.find(kV3Version); | 244 BlockIt version_it = header_block.find(kV3Version); |
248 BlockIt end_it = header_block.end(); | 245 BlockIt end_it = header_block.end(); |
249 if (status_it == end_it || version_it == end_it) { | 246 if (status_it == end_it || version_it == end_it) { |
250 return false; | 247 return false; |
251 } | 248 } |
252 | 249 |
253 if (!ParseReasonAndStatus(status_it->second, request_headers)) { | 250 if (!ParseReasonAndStatus(status_it->second, request_headers)) { |
254 return false; | 251 return false; |
255 } | 252 } |
256 request_headers->SetResponseVersion(version_it->second); | 253 request_headers->SetResponseVersion(version_it->second); |
257 for (BlockIt it = header_block.begin(); it != header_block.end(); ++it) { | 254 for (BlockIt it = header_block.begin(); it != header_block.end(); ++it) { |
258 if (!IsSpecialSpdyHeader(it, request_headers)) { | 255 if (!IsSpecialSpdyHeader(it, request_headers)) { |
259 request_headers->AppendHeader(it->first, it->second); | 256 request_headers->AppendHeader(it->first, it->second); |
260 } | 257 } |
261 } | 258 } |
262 return true; | 259 return true; |
263 } | 260 } |
264 | 261 |
265 } // namespace tools | 262 } // namespace tools |
266 } // namespace net | 263 } // namespace net |
OLD | NEW |