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 |