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

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

Issue 1340523002: Fix WebSocketServer extension parser. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ws-constructor-fix
Patch Set: Created 5 years, 2 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
« no previous file with comments | « net/server/web_socket.h ('k') | net/server/web_socket_encoder.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) 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/server/web_socket.h" 5 #include "net/server/web_socket.h"
6 6
7 #include <vector>
8
7 #include "base/base64.h" 9 #include "base/base64.h"
8 #include "base/logging.h" 10 #include "base/logging.h"
9 #include "base/sha1.h" 11 #include "base/sha1.h"
10 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
12 #include "base/sys_byteorder.h" 14 #include "base/sys_byteorder.h"
13 #include "net/server/http_connection.h" 15 #include "net/server/http_connection.h"
14 #include "net/server/http_server.h" 16 #include "net/server/http_server.h"
15 #include "net/server/http_server_request_info.h" 17 #include "net/server/http_server_request_info.h"
16 #include "net/server/http_server_response_info.h" 18 #include "net/server/http_server_response_info.h"
17 #include "net/server/web_socket_encoder.h" 19 #include "net/server/web_socket_encoder.h"
20 #include "net/websockets/websocket_deflate_parameters.h"
21 #include "net/websockets/websocket_extension.h"
22 #include "net/websockets/websocket_handshake_constants.h"
18 23
19 namespace net { 24 namespace net {
20 25
21 WebSocket::WebSocket(HttpServer* server, 26 namespace {
22 HttpConnection* connection, 27
23 const HttpServerRequestInfo& request) 28 std::string ExtensionsHeaderString(
24 : server_(server), connection_(connection), closed_(false) { 29 const std::vector<WebSocketExtension>& extensions) {
25 std::string request_extensions = 30 if (extensions.empty())
26 request.GetHeaderValue("sec-websocket-extensions"); 31 return std::string();
27 encoder_.reset(WebSocketEncoder::CreateServer(request_extensions, 32
28 &response_extensions_)); 33 std::string result = "Sec-WebSocket-Extensions: " + extensions[0].ToString();
29 if (!response_extensions_.empty()) { 34 for (size_t i = 1; i < extensions.size(); ++i)
30 response_extensions_ = 35 result += ", " + extensions[i].ToString();
31 "Sec-WebSocket-Extensions: " + response_extensions_ + "\r\n"; 36 return result + "\r\n";
32 }
33 } 37 }
34 38
39 std::string ValidResponseString(
40 const std::string& accept_hash,
41 const std::vector<WebSocketExtension> extensions) {
42 return base::StringPrintf(
43 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
44 "Upgrade: WebSocket\r\n"
45 "Connection: Upgrade\r\n"
46 "Sec-WebSocket-Accept: %s\r\n"
47 "%s"
48 "\r\n",
49 accept_hash.c_str(), ExtensionsHeaderString(extensions).c_str());
50 }
51
52 } // namespace
53
54 WebSocket::WebSocket(HttpServer* server, HttpConnection* connection)
55 : server_(server), connection_(connection), closed_(false) {}
56
35 WebSocket::~WebSocket() {} 57 WebSocket::~WebSocket() {}
36 58
37 scoped_ptr<WebSocket> WebSocket::CreateWebSocket( 59 void WebSocket::Accept(const HttpServerRequestInfo& request) {
38 HttpServer* server,
39 HttpConnection* connection,
40 const HttpServerRequestInfo& request) {
41 std::string version = request.GetHeaderValue("sec-websocket-version"); 60 std::string version = request.GetHeaderValue("sec-websocket-version");
42 if (version != "8" && version != "13") { 61 if (version != "8" && version != "13") {
43 server->SendResponse( 62 SendErrorResponse("Invalid request format. The version is not valid.");
44 connection->id(), 63 return;
45 HttpServerResponseInfo::CreateFor500(
46 "Invalid request format. The version is not valid."));
47 return nullptr;
48 } 64 }
49 65
50 std::string key = request.GetHeaderValue("sec-websocket-key"); 66 std::string key = request.GetHeaderValue("sec-websocket-key");
51 if (key.empty()) { 67 if (key.empty()) {
52 server->SendResponse( 68 SendErrorResponse(
53 connection->id(), 69 "Invalid request format. Sec-WebSocket-Key is empty or isn't "
54 HttpServerResponseInfo::CreateFor500( 70 "specified.");
55 "Invalid request format. Sec-WebSocket-Key is empty or isn't " 71 return;
56 "specified."));
57 return nullptr;
58 } 72 }
59 return make_scoped_ptr(new WebSocket(server, connection, request)); 73 std::string encoded_hash;
60 } 74 base::Base64Encode(base::SHA1HashString(key + websockets::kWebSocketGuid),
75 &encoded_hash);
61 76
62 void WebSocket::Accept(const HttpServerRequestInfo& request) { 77 std::vector<WebSocketExtension> response_extensions;
63 static const char* const kWebSocketGuid = 78 auto i = request.headers.find("sec-websocket-extensions");
64 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 79 if (i == request.headers.end()) {
65 std::string key = request.GetHeaderValue("sec-websocket-key"); 80 encoder_ = WebSocketEncoder::CreateServer();
66 std::string data = base::StringPrintf("%s%s", key.c_str(), kWebSocketGuid); 81 } else {
67 std::string encoded_hash; 82 WebSocketDeflateParameters params;
68 base::Base64Encode(base::SHA1HashString(data), &encoded_hash); 83 encoder_ = WebSocketEncoder::CreateServer(i->second, &params);
69 84 if (!encoder_) {
70 server_->SendRaw( 85 Fail();
71 connection_->id(), 86 return;
72 base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" 87 }
73 "Upgrade: WebSocket\r\n" 88 if (encoder_->deflate_enabled()) {
74 "Connection: Upgrade\r\n" 89 DCHECK(params.IsValidAsResponse());
75 "Sec-WebSocket-Accept: %s\r\n" 90 response_extensions.push_back(params.AsExtension());
76 "%s" 91 }
77 "\r\n", 92 }
78 encoded_hash.c_str(), response_extensions_.c_str())); 93 server_->SendRaw(connection_->id(),
94 ValidResponseString(encoded_hash, response_extensions));
79 } 95 }
80 96
81 WebSocket::ParseResult WebSocket::Read(std::string* message) { 97 WebSocket::ParseResult WebSocket::Read(std::string* message) {
98 if (closed_)
99 return FRAME_CLOSE;
100
82 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf(); 101 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf();
83 base::StringPiece frame(read_buf->StartOfBuffer(), read_buf->GetSize()); 102 base::StringPiece frame(read_buf->StartOfBuffer(), read_buf->GetSize());
84 int bytes_consumed = 0; 103 int bytes_consumed = 0;
85 ParseResult result = encoder_->DecodeFrame(frame, &bytes_consumed, message); 104 ParseResult result = encoder_->DecodeFrame(frame, &bytes_consumed, message);
86 if (result == FRAME_OK) 105 if (result == FRAME_OK)
87 read_buf->DidConsume(bytes_consumed); 106 read_buf->DidConsume(bytes_consumed);
88 if (result == FRAME_CLOSE) 107 if (result == FRAME_CLOSE)
89 closed_ = true; 108 closed_ = true;
90 return result; 109 return result;
91 } 110 }
92 111
93 void WebSocket::Send(const std::string& message) { 112 void WebSocket::Send(const std::string& message) {
94 if (closed_) 113 if (closed_)
95 return; 114 return;
96 std::string encoded; 115 std::string encoded;
97 encoder_->EncodeFrame(message, 0, &encoded); 116 encoder_->EncodeFrame(message, 0, &encoded);
98 server_->SendRaw(connection_->id(), encoded); 117 server_->SendRaw(connection_->id(), encoded);
99 } 118 }
100 119
120 void WebSocket::Fail() {
121 closed_ = true;
122 // TODO(yhirano): The server SHOULD log the problem.
123 server_->Close(connection_->id());
124 }
125
126 void WebSocket::SendErrorResponse(const std::string& message) {
127 if (closed_)
128 return;
129 closed_ = true;
130 server_->Send500(connection_->id(), message);
131 }
132
101 } // namespace net 133 } // namespace net
OLDNEW
« no previous file with comments | « net/server/web_socket.h ('k') | net/server/web_socket_encoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698