| 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/websockets/websocket_handshake_handler.h" | 5 #include "net/websockets/websocket_handshake_handler.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/sha1.h" | 10 #include "base/sha1.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/strings/string_piece.h" | 12 #include "base/strings/string_piece.h" |
| 13 #include "base/strings/string_tokenizer.h" | 13 #include "base/strings/string_tokenizer.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 16 #include "net/http/http_request_headers.h" | 16 #include "net/http/http_request_headers.h" |
| 17 #include "net/http/http_response_headers.h" | 17 #include "net/http/http_response_headers.h" |
| 18 #include "net/http/http_util.h" | 18 #include "net/http/http_util.h" |
| 19 #include "net/websockets/websocket_handshake_constants.h" | 19 #include "net/websockets/websocket_handshake_constants.h" |
| 20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
| 21 | 21 |
| 22 namespace net { | 22 namespace net { |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 const int kVersionHeaderValueForRFC6455 = 13; | 25 const int kVersionHeaderValueForRFC6455 = 13; |
| 26 | 26 |
| 27 // Splits |handshake_message| into Status-Line or Request-Line (including CRLF) | 27 // Splits |handshake_message| into Status-Line or Request-Line (including CRLF) |
| 28 // and headers (excluding 2nd CRLF of double CRLFs at the end of a handshake | 28 // and headers (excluding 2nd CRLF of double CRLFs at the end of a handshake |
| 29 // response). | 29 // response). |
| 30 void ParseHandshakeHeader( | 30 void ParseHandshakeHeader(const char* handshake_message, |
| 31 const char* handshake_message, int len, | 31 int len, |
| 32 std::string* request_line, | 32 std::string* request_line, |
| 33 std::string* headers) { | 33 std::string* headers) { |
| 34 size_t i = base::StringPiece(handshake_message, len).find_first_of("\r\n"); | 34 size_t i = base::StringPiece(handshake_message, len).find_first_of("\r\n"); |
| 35 if (i == base::StringPiece::npos) { | 35 if (i == base::StringPiece::npos) { |
| 36 *request_line = std::string(handshake_message, len); | 36 *request_line = std::string(handshake_message, len); |
| 37 *headers = ""; | 37 *headers = ""; |
| 38 return; | 38 return; |
| 39 } | 39 } |
| 40 // |request_line| includes \r\n. | 40 // |request_line| includes \r\n. |
| 41 *request_line = std::string(handshake_message, i + 2); | 41 *request_line = std::string(handshake_message, i + 2); |
| 42 | 42 |
| 43 int header_len = len - (i + 2) - 2; | 43 int header_len = len - (i + 2) - 2; |
| 44 if (header_len > 0) { | 44 if (header_len > 0) { |
| 45 // |handshake_message| includes trailing \r\n\r\n. | 45 // |handshake_message| includes trailing \r\n\r\n. |
| 46 // |headers| doesn't include 2nd \r\n. | 46 // |headers| doesn't include 2nd \r\n. |
| 47 *headers = std::string(handshake_message + i + 2, header_len); | 47 *headers = std::string(handshake_message + i + 2, header_len); |
| 48 } else { | 48 } else { |
| 49 *headers = ""; | 49 *headers = ""; |
| 50 } | 50 } |
| 51 } | 51 } |
| 52 | 52 |
| 53 void FetchHeaders(const std::string& headers, | 53 void FetchHeaders(const std::string& headers, |
| 54 const char* const headers_to_get[], | 54 const char* const headers_to_get[], |
| 55 size_t headers_to_get_len, | 55 size_t headers_to_get_len, |
| 56 std::vector<std::string>* values) { | 56 std::vector<std::string>* values) { |
| 57 net::HttpUtil::HeadersIterator iter(headers.begin(), headers.end(), "\r\n"); | 57 net::HttpUtil::HeadersIterator iter(headers.begin(), headers.end(), "\r\n"); |
| 58 while (iter.GetNext()) { | 58 while (iter.GetNext()) { |
| 59 for (size_t i = 0; i < headers_to_get_len; i++) { | 59 for (size_t i = 0; i < headers_to_get_len; i++) { |
| 60 if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), | 60 if (LowerCaseEqualsASCII( |
| 61 headers_to_get[i])) { | 61 iter.name_begin(), iter.name_end(), headers_to_get[i])) { |
| 62 values->push_back(iter.values()); | 62 values->push_back(iter.values()); |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 } | 66 } |
| 67 | 67 |
| 68 bool GetHeaderName(std::string::const_iterator line_begin, | 68 bool GetHeaderName(std::string::const_iterator line_begin, |
| 69 std::string::const_iterator line_end, | 69 std::string::const_iterator line_end, |
| 70 std::string::const_iterator* name_begin, | 70 std::string::const_iterator* name_begin, |
| 71 std::string::const_iterator* name_end) { | 71 std::string::const_iterator* name_end) { |
| 72 std::string::const_iterator colon = std::find(line_begin, line_end, ':'); | 72 std::string::const_iterator colon = std::find(line_begin, line_end, ':'); |
| 73 if (colon == line_end) { | 73 if (colon == line_end) { |
| 74 return false; | 74 return false; |
| 75 } | 75 } |
| 76 *name_begin = line_begin; | 76 *name_begin = line_begin; |
| 77 *name_end = colon; | 77 *name_end = colon; |
| 78 if (*name_begin == *name_end || net::HttpUtil::IsLWS(**name_begin)) | 78 if (*name_begin == *name_end || net::HttpUtil::IsLWS(**name_begin)) |
| 79 return false; | 79 return false; |
| 80 net::HttpUtil::TrimLWS(name_begin, name_end); | 80 net::HttpUtil::TrimLWS(name_begin, name_end); |
| 81 return true; | 81 return true; |
| 82 } | 82 } |
| 83 | 83 |
| 84 // Similar to HttpUtil::StripHeaders, but it preserves malformed headers, that | 84 // Similar to HttpUtil::StripHeaders, but it preserves malformed headers, that |
| 85 // is, lines that are not formatted as "<name>: <value>\r\n". | 85 // is, lines that are not formatted as "<name>: <value>\r\n". |
| 86 std::string FilterHeaders( | 86 std::string FilterHeaders(const std::string& headers, |
| 87 const std::string& headers, | 87 const char* const headers_to_remove[], |
| 88 const char* const headers_to_remove[], | 88 size_t headers_to_remove_len) { |
| 89 size_t headers_to_remove_len) { | |
| 90 std::string filtered_headers; | 89 std::string filtered_headers; |
| 91 | 90 |
| 92 base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n"); | 91 base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n"); |
| 93 while (lines.GetNext()) { | 92 while (lines.GetNext()) { |
| 94 std::string::const_iterator line_begin = lines.token_begin(); | 93 std::string::const_iterator line_begin = lines.token_begin(); |
| 95 std::string::const_iterator line_end = lines.token_end(); | 94 std::string::const_iterator line_end = lines.token_end(); |
| 96 std::string::const_iterator name_begin; | 95 std::string::const_iterator name_begin; |
| 97 std::string::const_iterator name_end; | 96 std::string::const_iterator name_end; |
| 98 bool should_remove = false; | 97 bool should_remove = false; |
| 99 if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) { | 98 if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) { |
| 100 for (size_t i = 0; i < headers_to_remove_len; ++i) { | 99 for (size_t i = 0; i < headers_to_remove_len; ++i) { |
| 101 if (LowerCaseEqualsASCII(name_begin, name_end, headers_to_remove[i])) { | 100 if (LowerCaseEqualsASCII(name_begin, name_end, headers_to_remove[i])) { |
| 102 should_remove = true; | 101 should_remove = true; |
| 103 break; | 102 break; |
| 104 } | 103 } |
| 105 } | 104 } |
| 106 } | 105 } |
| 107 if (!should_remove) { | 106 if (!should_remove) { |
| 108 filtered_headers.append(line_begin, line_end); | 107 filtered_headers.append(line_begin, line_end); |
| 109 filtered_headers.append("\r\n"); | 108 filtered_headers.append("\r\n"); |
| 110 } | 109 } |
| 111 } | 110 } |
| 112 return filtered_headers; | 111 return filtered_headers; |
| 113 } | 112 } |
| 114 | 113 |
| 115 bool CheckVersionInRequest(const std::string& request_headers) { | 114 bool CheckVersionInRequest(const std::string& request_headers) { |
| 116 std::vector<std::string> values; | 115 std::vector<std::string> values; |
| 117 const char* const headers_to_get[1] = { | 116 const char* const headers_to_get[1] = { |
| 118 websockets::kSecWebSocketVersionLowercase}; | 117 websockets::kSecWebSocketVersionLowercase}; |
| 119 FetchHeaders(request_headers, headers_to_get, 1, &values); | 118 FetchHeaders(request_headers, headers_to_get, 1, &values); |
| 120 DCHECK_LE(values.size(), 1U); | 119 DCHECK_LE(values.size(), 1U); |
| 121 if (values.empty()) | 120 if (values.empty()) |
| 122 return false; | 121 return false; |
| 123 | 122 |
| 124 int version; | 123 int version; |
| 125 bool conversion_success = base::StringToInt(values[0], &version); | 124 bool conversion_success = base::StringToInt(values[0], &version); |
| 126 if (!conversion_success) | 125 if (!conversion_success) |
| 127 return false; | 126 return false; |
| 128 | 127 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 145 response_message->reserve(response_message->size() + extra_size); | 144 response_message->reserve(response_message->size() + extra_size); |
| 146 response_message->append(header.begin(), header.end()); | 145 response_message->append(header.begin(), header.end()); |
| 147 response_message->append(kColonSpace, kColonSpace + kColonSpaceSize); | 146 response_message->append(kColonSpace, kColonSpace + kColonSpaceSize); |
| 148 response_message->append(value.begin(), value.end()); | 147 response_message->append(value.begin(), value.end()); |
| 149 response_message->append(kCrNl, kCrNl + kCrNlSize); | 148 response_message->append(kCrNl, kCrNl + kCrNlSize); |
| 150 } | 149 } |
| 151 | 150 |
| 152 } // namespace | 151 } // namespace |
| 153 | 152 |
| 154 WebSocketHandshakeRequestHandler::WebSocketHandshakeRequestHandler() | 153 WebSocketHandshakeRequestHandler::WebSocketHandshakeRequestHandler() |
| 155 : original_length_(0), | 154 : original_length_(0), raw_length_(0) { |
| 156 raw_length_(0) {} | 155 } |
| 157 | 156 |
| 158 bool WebSocketHandshakeRequestHandler::ParseRequest( | 157 bool WebSocketHandshakeRequestHandler::ParseRequest(const char* data, |
| 159 const char* data, int length) { | 158 int length) { |
| 160 DCHECK_GT(length, 0); | 159 DCHECK_GT(length, 0); |
| 161 std::string input(data, length); | 160 std::string input(data, length); |
| 162 int input_header_length = | 161 int input_header_length = |
| 163 HttpUtil::LocateEndOfHeaders(input.data(), input.size(), 0); | 162 HttpUtil::LocateEndOfHeaders(input.data(), input.size(), 0); |
| 164 if (input_header_length <= 0) | 163 if (input_header_length <= 0) |
| 165 return false; | 164 return false; |
| 166 | 165 |
| 167 ParseHandshakeHeader(input.data(), | 166 ParseHandshakeHeader( |
| 168 input_header_length, | 167 input.data(), input_header_length, &request_line_, &headers_); |
| 169 &request_line_, | |
| 170 &headers_); | |
| 171 | 168 |
| 172 if (!CheckVersionInRequest(headers_)) { | 169 if (!CheckVersionInRequest(headers_)) { |
| 173 NOTREACHED(); | 170 NOTREACHED(); |
| 174 return false; | 171 return false; |
| 175 } | 172 } |
| 176 | 173 |
| 177 original_length_ = input_header_length; | 174 original_length_ = input_header_length; |
| 178 return true; | 175 return true; |
| 179 } | 176 } |
| 180 | 177 |
| 181 size_t WebSocketHandshakeRequestHandler::original_length() const { | 178 size_t WebSocketHandshakeRequestHandler::original_length() const { |
| 182 return original_length_; | 179 return original_length_; |
| 183 } | 180 } |
| 184 | 181 |
| 185 void WebSocketHandshakeRequestHandler::AppendHeaderIfMissing( | 182 void WebSocketHandshakeRequestHandler::AppendHeaderIfMissing( |
| 186 const std::string& name, const std::string& value) { | 183 const std::string& name, |
| 184 const std::string& value) { |
| 187 DCHECK(!headers_.empty()); | 185 DCHECK(!headers_.empty()); |
| 188 HttpUtil::AppendHeaderIfMissing(name.c_str(), value, &headers_); | 186 HttpUtil::AppendHeaderIfMissing(name.c_str(), value, &headers_); |
| 189 } | 187 } |
| 190 | 188 |
| 191 void WebSocketHandshakeRequestHandler::RemoveHeaders( | 189 void WebSocketHandshakeRequestHandler::RemoveHeaders( |
| 192 const char* const headers_to_remove[], | 190 const char* const headers_to_remove[], |
| 193 size_t headers_to_remove_len) { | 191 size_t headers_to_remove_len) { |
| 194 DCHECK(!headers_.empty()); | 192 DCHECK(!headers_.empty()); |
| 195 headers_ = FilterHeaders( | 193 headers_ = FilterHeaders(headers_, headers_to_remove, headers_to_remove_len); |
| 196 headers_, headers_to_remove, headers_to_remove_len); | |
| 197 } | 194 } |
| 198 | 195 |
| 199 HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo( | 196 HttpRequestInfo WebSocketHandshakeRequestHandler::GetRequestInfo( |
| 200 const GURL& url, std::string* challenge) { | 197 const GURL& url, |
| 198 std::string* challenge) { |
| 201 HttpRequestInfo request_info; | 199 HttpRequestInfo request_info; |
| 202 request_info.url = url; | 200 request_info.url = url; |
| 203 size_t method_end = base::StringPiece(request_line_).find_first_of(" "); | 201 size_t method_end = base::StringPiece(request_line_).find_first_of(" "); |
| 204 if (method_end != base::StringPiece::npos) | 202 if (method_end != base::StringPiece::npos) |
| 205 request_info.method = std::string(request_line_.data(), method_end); | 203 request_info.method = std::string(request_line_.data(), method_end); |
| 206 | 204 |
| 207 request_info.extra_headers.Clear(); | 205 request_info.extra_headers.Clear(); |
| 208 request_info.extra_headers.AddHeadersFromString(headers_); | 206 request_info.extra_headers.AddHeadersFromString(headers_); |
| 209 | 207 |
| 210 request_info.extra_headers.RemoveHeader(websockets::kUpgrade); | 208 request_info.extra_headers.RemoveHeader(websockets::kUpgrade); |
| 211 request_info.extra_headers.RemoveHeader(HttpRequestHeaders::kConnection); | 209 request_info.extra_headers.RemoveHeader(HttpRequestHeaders::kConnection); |
| 212 | 210 |
| 213 std::string key; | 211 std::string key; |
| 214 bool header_present = request_info.extra_headers.GetHeader( | 212 bool header_present = |
| 215 websockets::kSecWebSocketKey, &key); | 213 request_info.extra_headers.GetHeader(websockets::kSecWebSocketKey, &key); |
| 216 DCHECK(header_present); | 214 DCHECK(header_present); |
| 217 request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey); | 215 request_info.extra_headers.RemoveHeader(websockets::kSecWebSocketKey); |
| 218 *challenge = key; | 216 *challenge = key; |
| 219 return request_info; | 217 return request_info; |
| 220 } | 218 } |
| 221 | 219 |
| 222 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock( | 220 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock( |
| 223 const GURL& url, | 221 const GURL& url, |
| 224 SpdyHeaderBlock* headers, | 222 SpdyHeaderBlock* headers, |
| 225 std::string* challenge, | 223 std::string* challenge, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 raw_length_ = raw_request.size(); | 297 raw_length_ = raw_request.size(); |
| 300 return raw_request; | 298 return raw_request; |
| 301 } | 299 } |
| 302 | 300 |
| 303 size_t WebSocketHandshakeRequestHandler::raw_length() const { | 301 size_t WebSocketHandshakeRequestHandler::raw_length() const { |
| 304 DCHECK_GT(raw_length_, 0); | 302 DCHECK_GT(raw_length_, 0); |
| 305 return raw_length_; | 303 return raw_length_; |
| 306 } | 304 } |
| 307 | 305 |
| 308 WebSocketHandshakeResponseHandler::WebSocketHandshakeResponseHandler() | 306 WebSocketHandshakeResponseHandler::WebSocketHandshakeResponseHandler() |
| 309 : original_header_length_(0) {} | 307 : original_header_length_(0) { |
| 308 } |
| 310 | 309 |
| 311 WebSocketHandshakeResponseHandler::~WebSocketHandshakeResponseHandler() {} | 310 WebSocketHandshakeResponseHandler::~WebSocketHandshakeResponseHandler() { |
| 311 } |
| 312 | 312 |
| 313 size_t WebSocketHandshakeResponseHandler::ParseRawResponse( | 313 size_t WebSocketHandshakeResponseHandler::ParseRawResponse(const char* data, |
| 314 const char* data, int length) { | 314 int length) { |
| 315 DCHECK_GT(length, 0); | 315 DCHECK_GT(length, 0); |
| 316 if (HasResponse()) { | 316 if (HasResponse()) { |
| 317 DCHECK(!status_line_.empty()); | 317 DCHECK(!status_line_.empty()); |
| 318 // headers_ might be empty for wrong response from server. | 318 // headers_ might be empty for wrong response from server. |
| 319 | 319 |
| 320 return 0; | 320 return 0; |
| 321 } | 321 } |
| 322 | 322 |
| 323 size_t old_original_length = original_.size(); | 323 size_t old_original_length = original_.size(); |
| 324 | 324 |
| 325 original_.append(data, length); | 325 original_.append(data, length); |
| 326 // TODO(ukai): fail fast when response gives wrong status code. | 326 // TODO(ukai): fail fast when response gives wrong status code. |
| 327 original_header_length_ = HttpUtil::LocateEndOfHeaders( | 327 original_header_length_ = |
| 328 original_.data(), original_.size(), 0); | 328 HttpUtil::LocateEndOfHeaders(original_.data(), original_.size(), 0); |
| 329 if (!HasResponse()) | 329 if (!HasResponse()) |
| 330 return length; | 330 return length; |
| 331 | 331 |
| 332 ParseHandshakeHeader(original_.data(), | 332 ParseHandshakeHeader( |
| 333 original_header_length_, | 333 original_.data(), original_header_length_, &status_line_, &headers_); |
| 334 &status_line_, | |
| 335 &headers_); | |
| 336 int header_size = status_line_.size() + headers_.size(); | 334 int header_size = status_line_.size() + headers_.size(); |
| 337 DCHECK_GE(original_header_length_, header_size); | 335 DCHECK_GE(original_header_length_, header_size); |
| 338 header_separator_ = std::string(original_.data() + header_size, | 336 header_separator_ = std::string(original_.data() + header_size, |
| 339 original_header_length_ - header_size); | 337 original_header_length_ - header_size); |
| 340 return original_header_length_ - old_original_length; | 338 return original_header_length_ - old_original_length; |
| 341 } | 339 } |
| 342 | 340 |
| 343 bool WebSocketHandshakeResponseHandler::HasResponse() const { | 341 bool WebSocketHandshakeResponseHandler::HasResponse() const { |
| 344 return original_header_length_ > 0 && | 342 return original_header_length_ > 0 && |
| 345 static_cast<size_t>(original_header_length_) <= original_.size(); | 343 static_cast<size_t>(original_header_length_) <= original_.size(); |
| 346 } | 344 } |
| 347 | 345 |
| 348 void ComputeSecWebSocketAccept(const std::string& key, | 346 void ComputeSecWebSocketAccept(const std::string& key, std::string* accept) { |
| 349 std::string* accept) { | |
| 350 DCHECK(accept); | 347 DCHECK(accept); |
| 351 | 348 |
| 352 std::string hash = | 349 std::string hash = base::SHA1HashString(key + websockets::kWebSocketGuid); |
| 353 base::SHA1HashString(key + websockets::kWebSocketGuid); | |
| 354 base::Base64Encode(hash, accept); | 350 base::Base64Encode(hash, accept); |
| 355 } | 351 } |
| 356 | 352 |
| 357 bool WebSocketHandshakeResponseHandler::ParseResponseInfo( | 353 bool WebSocketHandshakeResponseHandler::ParseResponseInfo( |
| 358 const HttpResponseInfo& response_info, | 354 const HttpResponseInfo& response_info, |
| 359 const std::string& challenge) { | 355 const std::string& challenge) { |
| 360 if (!response_info.headers.get()) | 356 if (!response_info.headers.get()) |
| 361 return false; | 357 return false; |
| 362 | 358 |
| 363 // TODO(ricea): Eliminate all the reallocations and string copies. | 359 // TODO(ricea): Eliminate all the reallocations and string copies. |
| 364 std::string response_message; | 360 std::string response_message; |
| 365 response_message = response_info.headers->GetStatusLine(); | 361 response_message = response_info.headers->GetStatusLine(); |
| 366 response_message += "\r\n"; | 362 response_message += "\r\n"; |
| 367 | 363 |
| 368 AppendHeader(websockets::kUpgrade, | 364 AppendHeader( |
| 369 websockets::kWebSocketLowercase, | 365 websockets::kUpgrade, websockets::kWebSocketLowercase, &response_message); |
| 370 &response_message); | |
| 371 | 366 |
| 372 AppendHeader( | 367 AppendHeader( |
| 373 HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message); | 368 HttpRequestHeaders::kConnection, websockets::kUpgrade, &response_message); |
| 374 | 369 |
| 375 std::string websocket_accept; | 370 std::string websocket_accept; |
| 376 ComputeSecWebSocketAccept(challenge, &websocket_accept); | 371 ComputeSecWebSocketAccept(challenge, &websocket_accept); |
| 377 AppendHeader( | 372 AppendHeader( |
| 378 websockets::kSecWebSocketAccept, websocket_accept, &response_message); | 373 websockets::kSecWebSocketAccept, websocket_accept, &response_message); |
| 379 | 374 |
| 380 void* iter = NULL; | 375 void* iter = NULL; |
| 381 std::string name; | 376 std::string name; |
| 382 std::string value; | 377 std::string value; |
| 383 while (response_info.headers->EnumerateHeaderLines(&iter, &name, &value)) { | 378 while (response_info.headers->EnumerateHeaderLines(&iter, &name, &value)) { |
| 384 AppendHeader(name, value, &response_message); | 379 AppendHeader(name, value, &response_message); |
| 385 } | 380 } |
| 386 response_message += "\r\n"; | 381 response_message += "\r\n"; |
| 387 | 382 |
| 388 return ParseRawResponse(response_message.data(), | 383 return ParseRawResponse(response_message.data(), response_message.size()) == |
| 389 response_message.size()) == response_message.size(); | 384 response_message.size(); |
| 390 } | 385 } |
| 391 | 386 |
| 392 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock( | 387 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock( |
| 393 const SpdyHeaderBlock& headers, | 388 const SpdyHeaderBlock& headers, |
| 394 const std::string& challenge, | 389 const std::string& challenge, |
| 395 int spdy_protocol_version) { | 390 int spdy_protocol_version) { |
| 396 SpdyHeaderBlock::const_iterator status; | 391 SpdyHeaderBlock::const_iterator status; |
| 397 if (spdy_protocol_version <= 2) | 392 if (spdy_protocol_version <= 2) |
| 398 status = headers.find("status"); | 393 status = headers.find("status"); |
| 399 else | 394 else |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 LowerCaseEqualsASCII(iter->first, | 441 LowerCaseEqualsASCII(iter->first, |
| 447 websockets::kSecWebSocketExtensionsSpdy3))) | 442 websockets::kSecWebSocketExtensionsSpdy3))) |
| 448 AppendHeader(iter->first.substr(1), tval, &response_message); | 443 AppendHeader(iter->first.substr(1), tval, &response_message); |
| 449 else | 444 else |
| 450 AppendHeader(iter->first, tval, &response_message); | 445 AppendHeader(iter->first, tval, &response_message); |
| 451 start = end + 1; | 446 start = end + 1; |
| 452 } while (end != std::string::npos); | 447 } while (end != std::string::npos); |
| 453 } | 448 } |
| 454 response_message += "\r\n"; | 449 response_message += "\r\n"; |
| 455 | 450 |
| 456 return ParseRawResponse(response_message.data(), | 451 return ParseRawResponse(response_message.data(), response_message.size()) == |
| 457 response_message.size()) == response_message.size(); | 452 response_message.size(); |
| 458 } | 453 } |
| 459 | 454 |
| 460 void WebSocketHandshakeResponseHandler::GetHeaders( | 455 void WebSocketHandshakeResponseHandler::GetHeaders( |
| 461 const char* const headers_to_get[], | 456 const char* const headers_to_get[], |
| 462 size_t headers_to_get_len, | 457 size_t headers_to_get_len, |
| 463 std::vector<std::string>* values) { | 458 std::vector<std::string>* values) { |
| 464 DCHECK(HasResponse()); | 459 DCHECK(HasResponse()); |
| 465 DCHECK(!status_line_.empty()); | 460 DCHECK(!status_line_.empty()); |
| 466 // headers_ might be empty for wrong response from server. | 461 // headers_ might be empty for wrong response from server. |
| 467 if (headers_.empty()) | 462 if (headers_.empty()) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 489 | 484 |
| 490 std::string WebSocketHandshakeResponseHandler::GetResponse() { | 485 std::string WebSocketHandshakeResponseHandler::GetResponse() { |
| 491 DCHECK(HasResponse()); | 486 DCHECK(HasResponse()); |
| 492 DCHECK(!status_line_.empty()); | 487 DCHECK(!status_line_.empty()); |
| 493 // headers_ might be empty for wrong response from server. | 488 // headers_ might be empty for wrong response from server. |
| 494 | 489 |
| 495 return status_line_ + headers_ + header_separator_; | 490 return status_line_ + headers_ + header_separator_; |
| 496 } | 491 } |
| 497 | 492 |
| 498 } // namespace net | 493 } // namespace net |
| OLD | NEW |