Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: net/websockets/websocket_handshake_handler.cc

Issue 10843050: WebSocket over SPDY: handshake support for both of SPDY/2 and SPDY/3 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase for landing Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 "base/base64.h" 7 #include "base/base64.h"
8 #include "base/md5.h" 8 #include "base/md5.h"
9 #include "base/sha1.h" 9 #include "base/sha1.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 request_info.extra_headers.RemoveHeader("Sec-WebSocket-Key2"); 259 request_info.extra_headers.RemoveHeader("Sec-WebSocket-Key2");
260 GetKeyNumber(key, challenge); 260 GetKeyNumber(key, challenge);
261 261
262 challenge->append(key3_); 262 challenge->append(key3_);
263 } 263 }
264 264
265 return request_info; 265 return request_info;
266 } 266 }
267 267
268 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock( 268 bool WebSocketHandshakeRequestHandler::GetRequestHeaderBlock(
269 const GURL& url, SpdyHeaderBlock* headers, std::string* challenge) { 269 const GURL& url,
270 SpdyHeaderBlock* headers,
271 std::string* challenge,
272 int spdy_protocol_version) {
270 // Construct opening handshake request headers as a SPDY header block. 273 // Construct opening handshake request headers as a SPDY header block.
271 // For details, see WebSocket Layering over SPDY/3 Draft 8. 274 // For details, see WebSocket Layering over SPDY/3 Draft 8.
272 (*headers)["path"] = url.path(); 275 if (spdy_protocol_version <= 2) {
273 (*headers)["version"] = 276 (*headers)["path"] = url.path();
277 (*headers)["version"] =
274 base::StringPrintf("%s%d", "WebSocket/", protocol_version_); 278 base::StringPrintf("%s%d", "WebSocket/", protocol_version_);
275 (*headers)["scheme"] = url.scheme(); 279 (*headers)["scheme"] = url.scheme();
280 } else {
281 (*headers)[":path"] = url.path();
282 (*headers)[":version"] =
283 base::StringPrintf("%s%d", "WebSocket/", protocol_version_);
284 (*headers)[":scheme"] = url.scheme();
285 }
276 286
277 HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n"); 287 HttpUtil::HeadersIterator iter(headers_.begin(), headers_.end(), "\r\n");
278 while (iter.GetNext()) { 288 while (iter.GetNext()) {
279 if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), "upgrade") || 289 if (LowerCaseEqualsASCII(iter.name_begin(), iter.name_end(), "upgrade") ||
280 LowerCaseEqualsASCII(iter.name_begin(), 290 LowerCaseEqualsASCII(iter.name_begin(),
281 iter.name_end(), 291 iter.name_end(),
282 "connection") || 292 "connection") ||
283 LowerCaseEqualsASCII(iter.name_begin(), 293 LowerCaseEqualsASCII(iter.name_begin(),
284 iter.name_end(), 294 iter.name_end(),
285 "sec-websocket-version")) { 295 "sec-websocket-version")) {
286 // These headers must be ignored. 296 // These headers must be ignored.
287 continue; 297 continue;
288 } else if (LowerCaseEqualsASCII(iter.name_begin(), 298 } else if (LowerCaseEqualsASCII(iter.name_begin(),
289 iter.name_end(), 299 iter.name_end(),
290 "sec-websocket-key")) { 300 "sec-websocket-key")) {
291 *challenge = iter.values(); 301 *challenge = iter.values();
292 // Sec-WebSocket-Key is not sent to a server. 302 // Sec-WebSocket-Key is not sent to a server.
293 continue; 303 continue;
304 } else if (LowerCaseEqualsASCII(iter.name_begin(),
305 iter.name_end(),
306 "host") ||
307 LowerCaseEqualsASCII(iter.name_begin(),
308 iter.name_end(),
309 "origin") ||
310 LowerCaseEqualsASCII(iter.name_begin(),
311 iter.name_end(),
312 "sec-websocket-protocol") ||
313 LowerCaseEqualsASCII(iter.name_begin(),
314 iter.name_end(),
315 "sec-websocket-extensions")) {
316 // TODO(toyoshim): Some WebSocket extensions may not be compatible with
317 // SPDY. We should omit them from a Sec-WebSocket-Extension header.
318 std::string name;
319 if (spdy_protocol_version <= 2)
320 name = StringToLowerASCII(iter.name());
321 else
322 name = ":" + StringToLowerASCII(iter.name());
323 (*headers)[name] = iter.values();
324 continue;
294 } 325 }
295 // Others should be sent out to |headers|. 326 // Others should be sent out to |headers|.
296 // TODO(toyoshim): Some WebSocket extensions are not compatible with SPDY.
297 // We should remove them from a Sec-WebSocket-Extension header.
298 std::string name = StringToLowerASCII(iter.name()); 327 std::string name = StringToLowerASCII(iter.name());
299 SpdyHeaderBlock::iterator found = headers->find(name); 328 SpdyHeaderBlock::iterator found = headers->find(name);
300 if (found == headers->end()) { 329 if (found == headers->end()) {
301 (*headers)[name] = iter.values(); 330 (*headers)[name] = iter.values();
302 } else { 331 } else {
303 // For now, websocket doesn't use multiple headers, but follows to http. 332 // For now, websocket doesn't use multiple headers, but follows to http.
304 found->second.append(1, '\0'); // +=() doesn't append 0's 333 found->second.append(1, '\0'); // +=() doesn't append 0's
305 found->second.append(iter.values()); 334 found->second.append(iter.values());
306 } 335 }
307 } 336 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 const char* digest_data = reinterpret_cast<char*>(digest.a); 449 const char* digest_data = reinterpret_cast<char*>(digest.a);
421 response_message.append(digest_data, sizeof(digest.a)); 450 response_message.append(digest_data, sizeof(digest.a));
422 } 451 }
423 452
424 return ParseRawResponse(response_message.data(), 453 return ParseRawResponse(response_message.data(),
425 response_message.size()) == response_message.size(); 454 response_message.size()) == response_message.size();
426 } 455 }
427 456
428 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock( 457 bool WebSocketHandshakeResponseHandler::ParseResponseHeaderBlock(
429 const SpdyHeaderBlock& headers, 458 const SpdyHeaderBlock& headers,
430 const std::string& challenge) { 459 const std::string& challenge,
431 std::string response_message; 460 int spdy_protocol_version) {
432 SpdyHeaderBlock::const_iterator status = headers.find("status"); 461 SpdyHeaderBlock::const_iterator status;
462 if (spdy_protocol_version <= 2)
463 status = headers.find("status");
464 else
465 status = headers.find(":status");
433 if (status == headers.end()) 466 if (status == headers.end())
434 return false; 467 return false;
468 std::string response_message;
435 response_message = 469 response_message =
436 base::StringPrintf("%s%s\r\n", "HTTP/1.1 ", status->second.c_str()); 470 base::StringPrintf("%s%s\r\n", "HTTP/1.1 ", status->second.c_str());
437 response_message += "Upgrade: websocket\r\n"; 471 response_message += "Upgrade: websocket\r\n";
438 response_message += "Connection: Upgrade\r\n"; 472 response_message += "Connection: Upgrade\r\n";
439 473
440 std::string hash = base::SHA1HashString(challenge + kWebSocketGuid); 474 std::string hash = base::SHA1HashString(challenge + kWebSocketGuid);
441 std::string websocket_accept; 475 std::string websocket_accept;
442 bool encode_success = base::Base64Encode(hash, &websocket_accept); 476 bool encode_success = base::Base64Encode(hash, &websocket_accept);
443 DCHECK(encode_success); 477 DCHECK(encode_success);
444 response_message += "Sec-WebSocket-Accept: " + websocket_accept + "\r\n"; 478 response_message += "Sec-WebSocket-Accept: " + websocket_accept + "\r\n";
445 479
446 for (SpdyHeaderBlock::const_iterator iter = headers.begin(); 480 for (SpdyHeaderBlock::const_iterator iter = headers.begin();
447 iter != headers.end(); 481 iter != headers.end();
448 ++iter) { 482 ++iter) {
449 // For each value, if the server sends a NUL-separated list of values, 483 // For each value, if the server sends a NUL-separated list of values,
450 // we separate that back out into individual headers for each value 484 // we separate that back out into individual headers for each value
451 // in the list. 485 // in the list.
452 if (LowerCaseEqualsASCII(iter->first, "status")) { 486 if ((spdy_protocol_version <= 2 &&
487 LowerCaseEqualsASCII(iter->first, "status")) ||
488 (spdy_protocol_version >= 3 &&
489 LowerCaseEqualsASCII(iter->first, ":status"))) {
453 // The status value is already handled as the first line of 490 // The status value is already handled as the first line of
454 // |response_message|. Just skip here. 491 // |response_message|. Just skip here.
455 continue; 492 continue;
456 } 493 }
457 const std::string& value = iter->second; 494 const std::string& value = iter->second;
458 size_t start = 0; 495 size_t start = 0;
459 size_t end = 0; 496 size_t end = 0;
460 do { 497 do {
461 end = value.find('\0', start); 498 end = value.find('\0', start);
462 std::string tval; 499 std::string tval;
463 if (end != std::string::npos) 500 if (end != std::string::npos)
464 tval = value.substr(start, (end - start)); 501 tval = value.substr(start, (end - start));
465 else 502 else
466 tval = value.substr(start); 503 tval = value.substr(start);
467 response_message += iter->first + ": " + tval + "\r\n"; 504 if (spdy_protocol_version >= 3 &&
505 (LowerCaseEqualsASCII(iter->first, ":sec-websocket-protocol") ||
506 LowerCaseEqualsASCII(iter->first, ":sec-websocket-extensions")))
507 response_message += iter->first.substr(1) + ": " + tval + "\r\n";
508 else
509 response_message += iter->first + ": " + tval + "\r\n";
468 start = end + 1; 510 start = end + 1;
469 } while (end != std::string::npos); 511 } while (end != std::string::npos);
470 } 512 }
471 response_message += "\r\n"; 513 response_message += "\r\n";
472 514
473 return ParseRawResponse(response_message.data(), 515 return ParseRawResponse(response_message.data(),
474 response_message.size()) == response_message.size(); 516 response_message.size()) == response_message.size();
475 } 517 }
476 518
477 void WebSocketHandshakeResponseHandler::GetHeaders( 519 void WebSocketHandshakeResponseHandler::GetHeaders(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 return status_line_ + headers_ + header_separator_ + key_; 556 return status_line_ + headers_ + header_separator_ + key_;
515 } 557 }
516 558
517 size_t WebSocketHandshakeResponseHandler::GetResponseKeySize() const { 559 size_t WebSocketHandshakeResponseHandler::GetResponseKeySize() const {
518 if (protocol_version_ >= kMinVersionOfHybiNewHandshake) 560 if (protocol_version_ >= kMinVersionOfHybiNewHandshake)
519 return 0; 561 return 0;
520 return kResponseKeySize; 562 return kResponseKeySize;
521 } 563 }
522 564
523 } // namespace net 565 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_handshake_handler.h ('k') | net/websockets/websocket_handshake_handler_spdy2_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698