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