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

Side by Side Diff: net/server/http_server.cc

Issue 7482041: DevTools: no way to remote debug using ToT build. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comments addressed Created 9 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
« no previous file with comments | « net/server/http_server.h ('k') | net/server/web_socket_frame.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/server/http_server.h" 5 #include "net/server/http_server.h"
6 6
7 #include "base/base64.h"
7 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
9 #include "base/md5.h" 10 #include "base/md5.h"
11 #include "base/sha1.h"
10 #include "base/string_number_conversions.h" 12 #include "base/string_number_conversions.h"
11 #include "base/string_util.h" 13 #include "base/string_util.h"
12 #include "base/stringprintf.h" 14 #include "base/stringprintf.h"
13 #include "build/build_config.h" 15 #include "build/build_config.h"
14 #include "net/server/http_server_request_info.h" 16 #include "net/server/http_server_request_info.h"
17 #include "net/server/web_socket_frame.h"
15 18
16 #if defined(OS_WIN) 19 #if defined(OS_WIN)
17 #include <winsock2.h> 20 #include <winsock2.h>
18 #else 21 #else
19 #include <arpa/inet.h> 22 #include <arpa/inet.h>
20 #endif 23 #endif
21 24
22 namespace net { 25 namespace net {
23 26
24 int HttpServer::Connection::lastId_ = 0; 27 int HttpServer::Connection::lastId_ = 0;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 spaces++; 63 spaces++;
61 } 64 }
62 if (spaces == 0) 65 if (spaces == 0)
63 return 0; 66 return 0;
64 int64 number = 0; 67 int64 number = 0;
65 if (!base::StringToInt64(result, &number)) 68 if (!base::StringToInt64(result, &number))
66 return 0; 69 return 0;
67 return htonl(static_cast<uint32>(number / spaces)); 70 return htonl(static_cast<uint32>(number / spaces));
68 } 71 }
69 72
70 void HttpServer::AcceptWebSocket( 73 void HttpServer::AcceptWebSocketHixie76(
71 int connection_id, 74 HttpServer::Connection* connection,
72 const HttpServerRequestInfo& request) { 75 const HttpServerRequestInfo& request) {
73 Connection* connection = FindConnection(connection_id);
74 if (connection == NULL)
75 return;
76
77 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1"); 76 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1");
78 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2"); 77 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2");
79 78
80 uint32 fp1 = WebSocketKeyFingerprint(key1); 79 uint32 fp1 = WebSocketKeyFingerprint(key1);
81 uint32 fp2 = WebSocketKeyFingerprint(key2); 80 uint32 fp2 = WebSocketKeyFingerprint(key2);
82 81
83 char data[16]; 82 char data[16];
84 memcpy(data, &fp1, 4); 83 memcpy(data, &fp1, 4);
85 memcpy(data + 4, &fp2, 4); 84 memcpy(data + 4, &fp2, 4);
86 memcpy(data + 8, &request.data[0], 8); 85 memcpy(data + 8, &request.data[0], 8);
(...skipping 10 matching lines...) Expand all
97 "Upgrade: WebSocket\r\n" 96 "Upgrade: WebSocket\r\n"
98 "Connection: Upgrade\r\n" 97 "Connection: Upgrade\r\n"
99 "Sec-WebSocket-Origin: %s\r\n" 98 "Sec-WebSocket-Origin: %s\r\n"
100 "Sec-WebSocket-Location: %s\r\n" 99 "Sec-WebSocket-Location: %s\r\n"
101 "\r\n", 100 "\r\n",
102 origin.c_str(), 101 origin.c_str(),
103 location.c_str())); 102 location.c_str()));
104 connection->socket_->Send(reinterpret_cast<char*>(digest.a), 16); 103 connection->socket_->Send(reinterpret_cast<char*>(digest.a), 16);
105 } 104 }
106 105
107 void HttpServer::SendOverWebSocket(int connection_id, 106 void HttpServer::SendOverWebSocketHixie76(HttpServer::Connection* connection,
108 const std::string& data) { 107 const std::string& data) {
109 Connection* connection = FindConnection(connection_id);
110 if (connection == NULL)
111 return;
112
113 DCHECK(connection->is_web_socket_);
114 char message_start = 0; 108 char message_start = 0;
115 char message_end = -1; 109 char message_end = -1;
116 connection->socket_->Send(&message_start, 1); 110 connection->socket_->Send(&message_start, 1);
117 connection->socket_->Send(data); 111 connection->socket_->Send(data);
118 connection->socket_->Send(&message_end, 1); 112 connection->socket_->Send(&message_end, 1);
119 } 113 }
120 114
121 void HttpServer::Send(int connection_id, const std::string& data) { 115 void HttpServer::Send(int connection_id, const std::string& data) {
122 Connection* connection = FindConnection(connection_id); 116 Connection* connection = FindConnection(connection_id);
123 if (connection == NULL) 117 if (connection == NULL)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 Connection* connection = FindConnection(connection_id); 176 Connection* connection = FindConnection(connection_id);
183 if (connection == NULL) 177 if (connection == NULL)
184 return; 178 return;
185 179
186 connection->DetachSocket(); 180 connection->DetachSocket();
187 } 181 }
188 182
189 HttpServer::Connection::Connection(HttpServer* server, ListenSocket* sock) 183 HttpServer::Connection::Connection(HttpServer* server, ListenSocket* sock)
190 : server_(server), 184 : server_(server),
191 socket_(sock), 185 socket_(sock),
192 is_web_socket_(false) { 186 is_web_socket_(false),
187 use_hixie76_web_socket_(false) {
193 id_ = lastId_++; 188 id_ = lastId_++;
194 } 189 }
195 190
196 HttpServer::Connection::~Connection() { 191 HttpServer::Connection::~Connection() {
197 DetachSocket(); 192 DetachSocket();
198 server_->delegate_->OnClose(id_); 193 server_->delegate_->OnClose(id_);
199 } 194 }
200 195
201 void HttpServer::Connection::DetachSocket() { 196 void HttpServer::Connection::DetachSocket() {
202 socket_ = NULL; 197 socket_ = NULL;
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 const char* data, 364 const char* data,
370 int len) { 365 int len) {
371 Connection* connection = FindConnection(socket); 366 Connection* connection = FindConnection(socket);
372 DCHECK(connection != NULL); 367 DCHECK(connection != NULL);
373 if (connection == NULL) 368 if (connection == NULL)
374 return; 369 return;
375 370
376 connection->recv_data_.append(data, len); 371 connection->recv_data_.append(data, len);
377 while (connection->recv_data_.length()) { 372 while (connection->recv_data_.length()) {
378 int pos = 0; 373 int pos = 0;
374 if (connection->is_web_socket_) {
375 if (connection->use_hixie76_web_socket_) {
376 HttpServerRequestInfo request;
377 if (!ParseHeaders(connection, &request, &pos))
pfeldman 2011/07/28 14:54:18 Please add FIXME suggesting that hixie76 frames ar
378 break;
379 delegate_->OnWebSocketMessage(connection->id_, request.data);
380 connection->Shift(pos);
381 } else {
382 std::string message;
383 if (!DidReadWebSocketHyBi10(
384 connection,
385 (char*)(connection->recv_data_.c_str() + pos),
386 connection->recv_data_.length() - pos,
387 &message))
388 break;
389 delegate_->OnWebSocketMessage(connection->id_, message);
390 }
391 continue;
392 }
393
379 HttpServerRequestInfo request; 394 HttpServerRequestInfo request;
380 if (!ParseHeaders(connection, &request, &pos)) 395 if (!ParseHeaders(connection, &request, &pos))
381 break; 396 break;
382 397
383 if (connection->is_web_socket_) {
384 delegate_->OnWebSocketMessage(connection->id_, request.data);
385 connection->Shift(pos);
386 continue;
387 }
388
389 std::string connection_header = GetHeaderValue(request, "Connection"); 398 std::string connection_header = GetHeaderValue(request, "Connection");
390 if (connection_header == "Upgrade") { 399 if (connection_header == "Upgrade") {
400 std::string version = GetHeaderValue(request, "Sec-WebSocket-Version");
401 if (version.length() && version == "8") {
402 std::string key = GetHeaderValue(request, "Sec-WebSocket-Key");
403 if (key.empty()) {
404 Send500(connection->id_,
405 "Invalid request format. "
406 "Sec-WebSocket-Key is empty or isn't specified.");
407 connection->Shift(pos);
408 break;
409 }
410
411 delegate_->OnWebSocketRequest(connection->id_, request);
412 connection->Shift(pos);
413 continue;
414 }
415
391 // Is this WebSocket and if yes, upgrade the connection. 416 // Is this WebSocket and if yes, upgrade the connection.
392 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1"); 417 std::string key1 = GetHeaderValue(request, "Sec-WebSocket-Key1");
393 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2"); 418 std::string key2 = GetHeaderValue(request, "Sec-WebSocket-Key2");
394 419
395 const int websocket_handshake_body_len = 8; 420 const int web_socket_handshake_body_len = 8;
396 if (pos + websocket_handshake_body_len > 421 if (pos + web_socket_handshake_body_len >
397 static_cast<int>(connection->recv_data_.length())) { 422 static_cast<int>(connection->recv_data_.length())) {
398 // We haven't received websocket handshake body yet. Wait. 423 // We haven't received websocket handshake body yet. Wait.
399 break; 424 break;
400 } 425 }
401 426
402 if (!key1.empty() && !key2.empty()) { 427 if (!key1.empty() && !key2.empty()) {
403 request.data = connection->recv_data_.substr( 428 request.data = connection->recv_data_.substr(
404 pos, 429 pos,
405 pos + websocket_handshake_body_len); 430 pos + web_socket_handshake_body_len);
406 pos += websocket_handshake_body_len; 431 pos += web_socket_handshake_body_len;
432 connection->use_hixie76_web_socket_ = true;
407 delegate_->OnWebSocketRequest(connection->id_, request); 433 delegate_->OnWebSocketRequest(connection->id_, request);
408 connection->Shift(pos); 434 connection->Shift(pos);
409 continue; 435 continue;
410 } 436 }
411 } 437 }
412 // Request body is not supported. It is always empty. 438 // Request body is not supported. It is always empty.
413 delegate_->OnHttpRequest(connection->id_, request); 439 delegate_->OnHttpRequest(connection->id_, request);
414 connection->Shift(pos); 440 connection->Shift(pos);
415 } 441 }
416 } 442 }
(...skipping 13 matching lines...) Expand all
430 return it->second; 456 return it->second;
431 } 457 }
432 458
433 HttpServer::Connection* HttpServer::FindConnection(ListenSocket* socket) { 459 HttpServer::Connection* HttpServer::FindConnection(ListenSocket* socket) {
434 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket); 460 SocketToConnectionMap::iterator it = socket_to_connection_.find(socket);
435 if (it == socket_to_connection_.end()) 461 if (it == socket_to_connection_.end())
436 return NULL; 462 return NULL;
437 return it->second; 463 return it->second;
438 } 464 }
439 465
466 void HttpServer::AcceptWebSocket(
467 int connection_id,
468 const HttpServerRequestInfo& request) {
469 Connection* connection = FindConnection(connection_id);
470 if (connection == NULL)
471 return;
472 if (connection->use_hixie76_web_socket_)
473 AcceptWebSocketHixie76(connection, request);
474 else
475 AcceptWebSocketHyBi10(connection, request);
476 }
477
478 static std::string GenerateWebSocketHyBi10AcceptKey(
479 const std::string& sec_web_socket_key)
480 {
481 static const char* const web_socket_key_GUID =
482 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
483 std::string data = base::StringPrintf("%s%s",
484 sec_web_socket_key.c_str(),
485 web_socket_key_GUID);
486 std::string encoded_hash;
487 base::Base64Encode(base::SHA1HashString(data), &encoded_hash);
488 return encoded_hash;
489 }
490
491 void HttpServer::AcceptWebSocketHyBi10(
492 HttpServer::Connection* connection,
493 const HttpServerRequestInfo& request) {
494 std::string key = GetHeaderValue(request, "Sec-WebSocket-Key");
495 connection->is_web_socket_ = true;
496
497 std::string response = base::StringPrintf(
498 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
pfeldman 2011/07/28 14:54:18 wrong indent
499 "Upgrade: WebSocket\r\n"
500 "Connection: Upgrade\r\n"
501 "Sec-WebSocket-Accept: %s\r\n"
502 "\r\n",
503 GenerateWebSocketHyBi10AcceptKey(key).c_str());
504 connection->socket_->Send(response);
505 }
506
507 void HttpServer::SendOverWebSocket(int connection_id,
508 const std::string& data) {
509 Connection* connection = FindConnection(connection_id);
510 if (connection == NULL)
511 return;
512 DCHECK(connection->is_web_socket_);
513 if (connection->use_hixie76_web_socket_)
pfeldman 2011/07/28 14:54:18 Having two web socket implementations with the sam
514 SendOverWebSocketHixie76(connection, data);
515 else
516 SendOverWebSocketHyBi10(connection, data);
517 }
518
519 void HttpServer::SendOverWebSocketHyBi10(HttpServer::Connection* connection,
520 const std::string& data) {
521 WebSocketFrame frame;
522 std::vector<char> buffer = frame.EncodeFrame(WebSocketFrame::kOpCodeText,
523 data.c_str(), data.length());
524 connection->socket_->Send(&buffer[0], buffer.size());
525 }
526
527 bool HttpServer::DidReadWebSocketHyBi10(HttpServer::Connection* connection,
528 char* data,
pfeldman 2011/07/28 14:54:18 poor indentation.
529 size_t length,
530 std::string* message) {
531 WebSocketFrame frame;
532 WebSocketFrame::ParseResult parse_result = frame.DecodeFrame(data, length);
533 if (parse_result == WebSocketFrame::FrameError)
534 return false;
535
536 if (parse_result == WebSocketFrame::FrameIncomplete)
537 return false;
538
539 CHECK(parse_result == WebSocketFrame::FrameOK);
540 *message = std::string(frame.payload_, frame.payload_length_);
541 connection->Shift(frame.frame_end_ - data);
542
543 return true;
544 }
545
440 } // namespace net 546 } // namespace net
OLDNEW
« no previous file with comments | « net/server/http_server.h ('k') | net/server/web_socket_frame.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698