| 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 |