| 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" |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 (base::LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), | 60 if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), |
| 61 headers_to_get[i])) { | 61 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) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 91 | 91 |
| 92 base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n"); | 92 base::StringTokenizer lines(headers.begin(), headers.end(), "\r\n"); |
| 93 while (lines.GetNext()) { | 93 while (lines.GetNext()) { |
| 94 std::string::const_iterator line_begin = lines.token_begin(); | 94 std::string::const_iterator line_begin = lines.token_begin(); |
| 95 std::string::const_iterator line_end = lines.token_end(); | 95 std::string::const_iterator line_end = lines.token_end(); |
| 96 std::string::const_iterator name_begin; | 96 std::string::const_iterator name_begin; |
| 97 std::string::const_iterator name_end; | 97 std::string::const_iterator name_end; |
| 98 bool should_remove = false; | 98 bool should_remove = false; |
| 99 if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) { | 99 if (GetHeaderName(line_begin, line_end, &name_begin, &name_end)) { |
| 100 for (size_t i = 0; i < headers_to_remove_len; ++i) { | 100 for (size_t i = 0; i < headers_to_remove_len; ++i) { |
| 101 if (base::LowerCaseEqualsASCII(name_begin, name_end, | 101 if (LowerCaseEqualsASCII(name_begin, name_end, headers_to_remove[i])) { |
| 102 headers_to_remove[i])) { | |
| 103 should_remove = true; | 102 should_remove = true; |
| 104 break; | 103 break; |
| 105 } | 104 } |
| 106 } | 105 } |
| 107 } | 106 } |
| 108 if (!should_remove) { | 107 if (!should_remove) { |
| 109 filtered_headers.append(line_begin, line_end); | 108 filtered_headers.append(line_begin, line_end); |
| 110 filtered_headers.append("\r\n"); | 109 filtered_headers.append("\r\n"); |
| 111 } | 110 } |
| 112 } | 111 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 (*headers)["version"] = "WebSocket/13"; | 231 (*headers)["version"] = "WebSocket/13"; |
| 233 (*headers)["scheme"] = url.scheme(); | 232 (*headers)["scheme"] = url.scheme(); |
| 234 } else { | 233 } else { |
| 235 (*headers)[":path"] = url.path(); | 234 (*headers)[":path"] = url.path(); |
| 236 (*headers)[":version"] = "WebSocket/13"; | 235 (*headers)[":version"] = "WebSocket/13"; |
| 237 (*headers)[":scheme"] = url.scheme(); | 236 (*headers)[":scheme"] = url.scheme(); |
| 238 } | 237 } |
| 239 | 238 |
| 240 HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n"); | 239 HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n"); |
| 241 while (iter.GetNext()) { | 240 while (iter.GetNext()) { |
| 242 if (base::LowerCaseEqualsASCII(iter.name_begin(), | 241 if (LowerCaseEqualsASCII(iter.name_begin(), |
| 243 iter.name_end(), | 242 iter.name_end(), |
| 244 websockets::kUpgradeLowercase) || | 243 websockets::kUpgradeLowercase) || |
| 245 base::LowerCaseEqualsASCII( | 244 LowerCaseEqualsASCII( |
| 246 iter.name_begin(), iter.name_end(), "connection") || | 245 iter.name_begin(), iter.name_end(), "connection") || |
| 247 base::LowerCaseEqualsASCII(iter.name_begin(), | 246 LowerCaseEqualsASCII(iter.name_begin(), |
| 248 iter.name_end(), | 247 iter.name_end(), |
| 249 websockets::kSecWebSocketVersionLowercase)) { | 248 websockets::kSecWebSocketVersionLowercase)) { |
| 250 // These headers must be ignored. | 249 // These headers must be ignored. |
| 251 continue; | 250 continue; |
| 252 } else if (base::LowerCaseEqualsASCII( | 251 } else if (LowerCaseEqualsASCII(iter.name_begin(), |
| 253 iter.name_begin(), iter.name_end(), | 252 iter.name_end(), |
| 254 websockets::kSecWebSocketKeyLowercase)) { | 253 websockets::kSecWebSocketKeyLowercase)) { |
| 255 *challenge = iter.values(); | 254 *challenge = iter.values(); |
| 256 // Sec-WebSocket-Key is not sent to the server. | 255 // Sec-WebSocket-Key is not sent to the server. |
| 257 continue; | 256 continue; |
| 258 } else if (base::LowerCaseEqualsASCII( | 257 } else if (LowerCaseEqualsASCII( |
| 259 iter.name_begin(), iter.name_end(), "host") || | 258 iter.name_begin(), iter.name_end(), "host") || |
| 260 base::LowerCaseEqualsASCII( | 259 LowerCaseEqualsASCII( |
| 261 iter.name_begin(), iter.name_end(), "origin") || | 260 iter.name_begin(), iter.name_end(), "origin") || |
| 262 base::LowerCaseEqualsASCII( | 261 LowerCaseEqualsASCII( |
| 263 iter.name_begin(), | 262 iter.name_begin(), |
| 264 iter.name_end(), | 263 iter.name_end(), |
| 265 websockets::kSecWebSocketProtocolLowercase) || | 264 websockets::kSecWebSocketProtocolLowercase) || |
| 266 base::LowerCaseEqualsASCII( | 265 LowerCaseEqualsASCII( |
| 267 iter.name_begin(), | 266 iter.name_begin(), |
| 268 iter.name_end(), | 267 iter.name_end(), |
| 269 websockets::kSecWebSocketExtensionsLowercase)) { | 268 websockets::kSecWebSocketExtensionsLowercase)) { |
| 270 // TODO(toyoshim): Some WebSocket extensions may not be compatible with | 269 // TODO(toyoshim): Some WebSocket extensions may not be compatible with |
| 271 // SPDY. We should omit them from a Sec-WebSocket-Extension header. | 270 // SPDY. We should omit them from a Sec-WebSocket-Extension header. |
| 272 std::string name; | 271 std::string name; |
| 273 if (spdy_protocol_version <= 2) | 272 if (spdy_protocol_version <= 2) |
| 274 name = base::StringToLowerASCII(iter.name()); | 273 name = base::StringToLowerASCII(iter.name()); |
| 275 else | 274 else |
| 276 name = ":" + base::StringToLowerASCII(iter.name()); | 275 name = ":" + base::StringToLowerASCII(iter.name()); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 AppendHeader( | 416 AppendHeader( |
| 418 websockets::kSecWebSocketAccept, websocket_accept, &response_message); | 417 websockets::kSecWebSocketAccept, websocket_accept, &response_message); |
| 419 | 418 |
| 420 for (SpdyHeaderBlock::const_iterator iter = headers.begin(); | 419 for (SpdyHeaderBlock::const_iterator iter = headers.begin(); |
| 421 iter != headers.end(); | 420 iter != headers.end(); |
| 422 ++iter) { | 421 ++iter) { |
| 423 // For each value, if the server sends a NUL-separated list of values, | 422 // For each value, if the server sends a NUL-separated list of values, |
| 424 // we separate that back out into individual headers for each value | 423 // we separate that back out into individual headers for each value |
| 425 // in the list. | 424 // in the list. |
| 426 if ((spdy_protocol_version <= 2 && | 425 if ((spdy_protocol_version <= 2 && |
| 427 base::LowerCaseEqualsASCII(iter->first, "status")) || | 426 LowerCaseEqualsASCII(iter->first, "status")) || |
| 428 (spdy_protocol_version >= 3 && | 427 (spdy_protocol_version >= 3 && |
| 429 base::LowerCaseEqualsASCII(iter->first, ":status"))) { | 428 LowerCaseEqualsASCII(iter->first, ":status"))) { |
| 430 // The status value is already handled as the first line of | 429 // The status value is already handled as the first line of |
| 431 // |response_message|. Just skip here. | 430 // |response_message|. Just skip here. |
| 432 continue; | 431 continue; |
| 433 } | 432 } |
| 434 const std::string& value = iter->second; | 433 const std::string& value = iter->second; |
| 435 size_t start = 0; | 434 size_t start = 0; |
| 436 size_t end = 0; | 435 size_t end = 0; |
| 437 do { | 436 do { |
| 438 end = value.find('\0', start); | 437 end = value.find('\0', start); |
| 439 std::string tval; | 438 std::string tval; |
| 440 if (end != std::string::npos) | 439 if (end != std::string::npos) |
| 441 tval = value.substr(start, (end - start)); | 440 tval = value.substr(start, (end - start)); |
| 442 else | 441 else |
| 443 tval = value.substr(start); | 442 tval = value.substr(start); |
| 444 if (spdy_protocol_version >= 3 && | 443 if (spdy_protocol_version >= 3 && |
| 445 (base::LowerCaseEqualsASCII(iter->first, | 444 (LowerCaseEqualsASCII(iter->first, |
| 446 websockets::kSecWebSocketProtocolSpdy3) || | 445 websockets::kSecWebSocketProtocolSpdy3) || |
| 447 base::LowerCaseEqualsASCII(iter->first, | 446 LowerCaseEqualsASCII(iter->first, |
| 448 websockets::kSecWebSocketExtensionsSpdy3))) | 447 websockets::kSecWebSocketExtensionsSpdy3))) |
| 449 AppendHeader(iter->first.substr(1), tval, &response_message); | 448 AppendHeader(iter->first.substr(1), tval, &response_message); |
| 450 else | 449 else |
| 451 AppendHeader(iter->first, tval, &response_message); | 450 AppendHeader(iter->first, tval, &response_message); |
| 452 start = end + 1; | 451 start = end + 1; |
| 453 } while (end != std::string::npos); | 452 } while (end != std::string::npos); |
| 454 } | 453 } |
| 455 response_message += "\r\n"; | 454 response_message += "\r\n"; |
| 456 | 455 |
| 457 return ParseRawResponse(response_message.data(), | 456 return ParseRawResponse(response_message.data(), |
| 458 response_message.size()) == response_message.size(); | 457 response_message.size()) == response_message.size(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 | 489 |
| 491 std::string WebSocketHandshakeResponseHandler::GetResponse() { | 490 std::string WebSocketHandshakeResponseHandler::GetResponse() { |
| 492 DCHECK(HasResponse()); | 491 DCHECK(HasResponse()); |
| 493 DCHECK(!status_line_.empty()); | 492 DCHECK(!status_line_.empty()); |
| 494 // headers_ might be empty for wrong response from server. | 493 // headers_ might be empty for wrong response from server. |
| 495 | 494 |
| 496 return status_line_ + headers_ + header_separator_; | 495 return status_line_ + headers_ + header_separator_; |
| 497 } | 496 } |
| 498 | 497 |
| 499 } // namespace net | 498 } // namespace net |
| OLD | NEW |