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