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

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

Issue 497223003: Revert of Replace StreamListenSocket with StreamSocket in HttpServer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
« no previous file with comments | « net/server/web_socket.h ('k') | net/socket/server_socket.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 <limits> 7 #include <limits>
8 8
9 #include "base/base64.h" 9 #include "base/base64.h"
10 #include "base/rand_util.h" 10 #include "base/rand_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/md5.h" 12 #include "base/md5.h"
13 #include "base/sha1.h" 13 #include "base/sha1.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "base/sys_byteorder.h" 16 #include "base/sys_byteorder.h"
17 #include "net/server/http_connection.h" 17 #include "net/server/http_connection.h"
18 #include "net/server/http_server.h"
19 #include "net/server/http_server_request_info.h" 18 #include "net/server/http_server_request_info.h"
20 #include "net/server/http_server_response_info.h" 19 #include "net/server/http_server_response_info.h"
21 20
22 namespace net { 21 namespace net {
23 22
24 namespace { 23 namespace {
25 24
26 static uint32 WebSocketKeyFingerprint(const std::string& str) { 25 static uint32 WebSocketKeyFingerprint(const std::string& str) {
27 std::string result; 26 std::string result;
28 const char* p_char = str.c_str(); 27 const char* p_char = str.c_str();
29 int length = str.length(); 28 int length = str.length();
30 int spaces = 0; 29 int spaces = 0;
31 for (int i = 0; i < length; ++i) { 30 for (int i = 0; i < length; ++i) {
32 if (p_char[i] >= '0' && p_char[i] <= '9') 31 if (p_char[i] >= '0' && p_char[i] <= '9')
33 result.append(&p_char[i], 1); 32 result.append(&p_char[i], 1);
34 else if (p_char[i] == ' ') 33 else if (p_char[i] == ' ')
35 spaces++; 34 spaces++;
36 } 35 }
37 if (spaces == 0) 36 if (spaces == 0)
38 return 0; 37 return 0;
39 int64 number = 0; 38 int64 number = 0;
40 if (!base::StringToInt64(result, &number)) 39 if (!base::StringToInt64(result, &number))
41 return 0; 40 return 0;
42 return base::HostToNet32(static_cast<uint32>(number / spaces)); 41 return base::HostToNet32(static_cast<uint32>(number / spaces));
43 } 42 }
44 43
45 class WebSocketHixie76 : public net::WebSocket { 44 class WebSocketHixie76 : public net::WebSocket {
46 public: 45 public:
47 static net::WebSocket* Create(HttpServer* server, 46 static net::WebSocket* Create(HttpConnection* connection,
48 HttpConnection* connection,
49 const HttpServerRequestInfo& request, 47 const HttpServerRequestInfo& request,
50 size_t* pos) { 48 size_t* pos) {
51 if (connection->read_buf()->GetSize() < 49 if (connection->recv_data().length() < *pos + kWebSocketHandshakeBodyLen)
52 static_cast<int>(*pos + kWebSocketHandshakeBodyLen))
53 return NULL; 50 return NULL;
54 return new WebSocketHixie76(server, connection, request, pos); 51 return new WebSocketHixie76(connection, request, pos);
55 } 52 }
56 53
57 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE { 54 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE {
58 std::string key1 = request.GetHeaderValue("sec-websocket-key1"); 55 std::string key1 = request.GetHeaderValue("sec-websocket-key1");
59 std::string key2 = request.GetHeaderValue("sec-websocket-key2"); 56 std::string key2 = request.GetHeaderValue("sec-websocket-key2");
60 57
61 uint32 fp1 = WebSocketKeyFingerprint(key1); 58 uint32 fp1 = WebSocketKeyFingerprint(key1);
62 uint32 fp2 = WebSocketKeyFingerprint(key2); 59 uint32 fp2 = WebSocketKeyFingerprint(key2);
63 60
64 char data[16]; 61 char data[16];
65 memcpy(data, &fp1, 4); 62 memcpy(data, &fp1, 4);
66 memcpy(data + 4, &fp2, 4); 63 memcpy(data + 4, &fp2, 4);
67 memcpy(data + 8, &key3_[0], 8); 64 memcpy(data + 8, &key3_[0], 8);
68 65
69 base::MD5Digest digest; 66 base::MD5Digest digest;
70 base::MD5Sum(data, 16, &digest); 67 base::MD5Sum(data, 16, &digest);
71 68
72 std::string origin = request.GetHeaderValue("origin"); 69 std::string origin = request.GetHeaderValue("origin");
73 std::string host = request.GetHeaderValue("host"); 70 std::string host = request.GetHeaderValue("host");
74 std::string location = "ws://" + host + request.path; 71 std::string location = "ws://" + host + request.path;
75 server_->SendRaw( 72 connection_->Send(base::StringPrintf(
76 connection_->id(), 73 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
77 base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" 74 "Upgrade: WebSocket\r\n"
78 "Upgrade: WebSocket\r\n" 75 "Connection: Upgrade\r\n"
79 "Connection: Upgrade\r\n" 76 "Sec-WebSocket-Origin: %s\r\n"
80 "Sec-WebSocket-Origin: %s\r\n" 77 "Sec-WebSocket-Location: %s\r\n"
81 "Sec-WebSocket-Location: %s\r\n" 78 "\r\n",
82 "\r\n", 79 origin.c_str(),
83 origin.c_str(), 80 location.c_str()));
84 location.c_str())); 81 connection_->Send(reinterpret_cast<char*>(digest.a), 16);
85 server_->SendRaw(connection_->id(),
86 std::string(reinterpret_cast<char*>(digest.a), 16));
87 } 82 }
88 83
89 virtual ParseResult Read(std::string* message) OVERRIDE { 84 virtual ParseResult Read(std::string* message) OVERRIDE {
90 DCHECK(message); 85 DCHECK(message);
91 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf(); 86 const std::string& data = connection_->recv_data();
92 if (read_buf->StartOfBuffer()[0]) 87 if (data[0])
93 return FRAME_ERROR; 88 return FRAME_ERROR;
94 89
95 base::StringPiece data(read_buf->StartOfBuffer(), read_buf->GetSize());
96 size_t pos = data.find('\377', 1); 90 size_t pos = data.find('\377', 1);
97 if (pos == base::StringPiece::npos) 91 if (pos == std::string::npos)
98 return FRAME_INCOMPLETE; 92 return FRAME_INCOMPLETE;
99 93
100 message->assign(data.data() + 1, pos - 1); 94 std::string buffer(data.begin() + 1, data.begin() + pos);
101 read_buf->DidConsume(pos + 1); 95 message->swap(buffer);
96 connection_->Shift(pos + 1);
102 97
103 return FRAME_OK; 98 return FRAME_OK;
104 } 99 }
105 100
106 virtual void Send(const std::string& message) OVERRIDE { 101 virtual void Send(const std::string& message) OVERRIDE {
107 char message_start = 0; 102 char message_start = 0;
108 char message_end = -1; 103 char message_end = -1;
109 server_->SendRaw(connection_->id(), std::string(1, message_start)); 104 connection_->Send(&message_start, 1);
110 server_->SendRaw(connection_->id(), message); 105 connection_->Send(message);
111 server_->SendRaw(connection_->id(), std::string(1, message_end)); 106 connection_->Send(&message_end, 1);
112 } 107 }
113 108
114 private: 109 private:
115 static const int kWebSocketHandshakeBodyLen; 110 static const int kWebSocketHandshakeBodyLen;
116 111
117 WebSocketHixie76(HttpServer* server, 112 WebSocketHixie76(HttpConnection* connection,
118 HttpConnection* connection,
119 const HttpServerRequestInfo& request, 113 const HttpServerRequestInfo& request,
120 size_t* pos) 114 size_t* pos) : WebSocket(connection) {
121 : WebSocket(server, connection) {
122 std::string key1 = request.GetHeaderValue("sec-websocket-key1"); 115 std::string key1 = request.GetHeaderValue("sec-websocket-key1");
123 std::string key2 = request.GetHeaderValue("sec-websocket-key2"); 116 std::string key2 = request.GetHeaderValue("sec-websocket-key2");
124 117
125 if (key1.empty()) { 118 if (key1.empty()) {
126 server->SendResponse( 119 connection->Send(HttpServerResponseInfo::CreateFor500(
127 connection->id(), 120 "Invalid request format. Sec-WebSocket-Key1 is empty or isn't "
128 HttpServerResponseInfo::CreateFor500( 121 "specified."));
129 "Invalid request format. Sec-WebSocket-Key1 is empty or isn't "
130 "specified."));
131 return; 122 return;
132 } 123 }
133 124
134 if (key2.empty()) { 125 if (key2.empty()) {
135 server->SendResponse( 126 connection->Send(HttpServerResponseInfo::CreateFor500(
136 connection->id(), 127 "Invalid request format. Sec-WebSocket-Key2 is empty or isn't "
137 HttpServerResponseInfo::CreateFor500( 128 "specified."));
138 "Invalid request format. Sec-WebSocket-Key2 is empty or isn't "
139 "specified."));
140 return; 129 return;
141 } 130 }
142 131
143 key3_.assign(connection->read_buf()->StartOfBuffer() + *pos, 132 key3_ = connection->recv_data().substr(
144 kWebSocketHandshakeBodyLen); 133 *pos,
134 *pos + kWebSocketHandshakeBodyLen);
145 *pos += kWebSocketHandshakeBodyLen; 135 *pos += kWebSocketHandshakeBodyLen;
146 } 136 }
147 137
148 std::string key3_; 138 std::string key3_;
149 139
150 DISALLOW_COPY_AND_ASSIGN(WebSocketHixie76); 140 DISALLOW_COPY_AND_ASSIGN(WebSocketHixie76);
151 }; 141 };
152 142
153 const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8; 143 const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8;
154 144
(...skipping 17 matching lines...) Expand all
172 const unsigned char kMaskBit = 0x80; 162 const unsigned char kMaskBit = 0x80;
173 const unsigned char kPayloadLengthMask = 0x7F; 163 const unsigned char kPayloadLengthMask = 0x7F;
174 164
175 const size_t kMaxSingleBytePayloadLength = 125; 165 const size_t kMaxSingleBytePayloadLength = 125;
176 const size_t kTwoBytePayloadLengthField = 126; 166 const size_t kTwoBytePayloadLengthField = 126;
177 const size_t kEightBytePayloadLengthField = 127; 167 const size_t kEightBytePayloadLengthField = 127;
178 const size_t kMaskingKeyWidthInBytes = 4; 168 const size_t kMaskingKeyWidthInBytes = 4;
179 169
180 class WebSocketHybi17 : public WebSocket { 170 class WebSocketHybi17 : public WebSocket {
181 public: 171 public:
182 static WebSocket* Create(HttpServer* server, 172 static WebSocket* Create(HttpConnection* connection,
183 HttpConnection* connection,
184 const HttpServerRequestInfo& request, 173 const HttpServerRequestInfo& request,
185 size_t* pos) { 174 size_t* pos) {
186 std::string version = request.GetHeaderValue("sec-websocket-version"); 175 std::string version = request.GetHeaderValue("sec-websocket-version");
187 if (version != "8" && version != "13") 176 if (version != "8" && version != "13")
188 return NULL; 177 return NULL;
189 178
190 std::string key = request.GetHeaderValue("sec-websocket-key"); 179 std::string key = request.GetHeaderValue("sec-websocket-key");
191 if (key.empty()) { 180 if (key.empty()) {
192 server->SendResponse( 181 connection->Send(HttpServerResponseInfo::CreateFor500(
193 connection->id(), 182 "Invalid request format. Sec-WebSocket-Key is empty or isn't "
194 HttpServerResponseInfo::CreateFor500( 183 "specified."));
195 "Invalid request format. Sec-WebSocket-Key is empty or isn't "
196 "specified."));
197 return NULL; 184 return NULL;
198 } 185 }
199 return new WebSocketHybi17(server, connection, request, pos); 186 return new WebSocketHybi17(connection, request, pos);
200 } 187 }
201 188
202 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE { 189 virtual void Accept(const HttpServerRequestInfo& request) OVERRIDE {
203 static const char* const kWebSocketGuid = 190 static const char* const kWebSocketGuid =
204 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; 191 "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
205 std::string key = request.GetHeaderValue("sec-websocket-key"); 192 std::string key = request.GetHeaderValue("sec-websocket-key");
206 std::string data = base::StringPrintf("%s%s", key.c_str(), kWebSocketGuid); 193 std::string data = base::StringPrintf("%s%s", key.c_str(), kWebSocketGuid);
207 std::string encoded_hash; 194 std::string encoded_hash;
208 base::Base64Encode(base::SHA1HashString(data), &encoded_hash); 195 base::Base64Encode(base::SHA1HashString(data), &encoded_hash);
209 196
210 server_->SendRaw( 197 std::string response = base::StringPrintf(
211 connection_->id(), 198 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n"
212 base::StringPrintf("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" 199 "Upgrade: WebSocket\r\n"
213 "Upgrade: WebSocket\r\n" 200 "Connection: Upgrade\r\n"
214 "Connection: Upgrade\r\n" 201 "Sec-WebSocket-Accept: %s\r\n"
215 "Sec-WebSocket-Accept: %s\r\n" 202 "\r\n",
216 "\r\n", 203 encoded_hash.c_str());
217 encoded_hash.c_str())); 204 connection_->Send(response);
218 } 205 }
219 206
220 virtual ParseResult Read(std::string* message) OVERRIDE { 207 virtual ParseResult Read(std::string* message) OVERRIDE {
221 HttpConnection::ReadIOBuffer* read_buf = connection_->read_buf(); 208 const std::string& frame = connection_->recv_data();
222 base::StringPiece frame(read_buf->StartOfBuffer(), read_buf->GetSize());
223 int bytes_consumed = 0; 209 int bytes_consumed = 0;
210
224 ParseResult result = 211 ParseResult result =
225 WebSocket::DecodeFrameHybi17(frame, true, &bytes_consumed, message); 212 WebSocket::DecodeFrameHybi17(frame, true, &bytes_consumed, message);
226 if (result == FRAME_OK) 213 if (result == FRAME_OK)
227 read_buf->DidConsume(bytes_consumed); 214 connection_->Shift(bytes_consumed);
228 if (result == FRAME_CLOSE) 215 if (result == FRAME_CLOSE)
229 closed_ = true; 216 closed_ = true;
230 return result; 217 return result;
231 } 218 }
232 219
233 virtual void Send(const std::string& message) OVERRIDE { 220 virtual void Send(const std::string& message) OVERRIDE {
234 if (closed_) 221 if (closed_)
235 return; 222 return;
236 server_->SendRaw(connection_->id(), 223 std::string data = WebSocket::EncodeFrameHybi17(message, 0);
237 WebSocket::EncodeFrameHybi17(message, 0)); 224 connection_->Send(data);
238 } 225 }
239 226
240 private: 227 private:
241 WebSocketHybi17(HttpServer* server, 228 WebSocketHybi17(HttpConnection* connection,
242 HttpConnection* connection,
243 const HttpServerRequestInfo& request, 229 const HttpServerRequestInfo& request,
244 size_t* pos) 230 size_t* pos)
245 : WebSocket(server, connection), 231 : WebSocket(connection),
246 op_code_(0), 232 op_code_(0),
247 final_(false), 233 final_(false),
248 reserved1_(false), 234 reserved1_(false),
249 reserved2_(false), 235 reserved2_(false),
250 reserved3_(false), 236 reserved3_(false),
251 masked_(false), 237 masked_(false),
252 payload_(0), 238 payload_(0),
253 payload_length_(0), 239 payload_length_(0),
254 frame_end_(0), 240 frame_end_(0),
255 closed_(false) { 241 closed_(false) {
256 } 242 }
257 243
258 OpCode op_code_; 244 OpCode op_code_;
259 bool final_; 245 bool final_;
260 bool reserved1_; 246 bool reserved1_;
261 bool reserved2_; 247 bool reserved2_;
262 bool reserved3_; 248 bool reserved3_;
263 bool masked_; 249 bool masked_;
264 const char* payload_; 250 const char* payload_;
265 size_t payload_length_; 251 size_t payload_length_;
266 const char* frame_end_; 252 const char* frame_end_;
267 bool closed_; 253 bool closed_;
268 254
269 DISALLOW_COPY_AND_ASSIGN(WebSocketHybi17); 255 DISALLOW_COPY_AND_ASSIGN(WebSocketHybi17);
270 }; 256 };
271 257
272 } // anonymous namespace 258 } // anonymous namespace
273 259
274 WebSocket* WebSocket::CreateWebSocket(HttpServer* server, 260 WebSocket* WebSocket::CreateWebSocket(HttpConnection* connection,
275 HttpConnection* connection,
276 const HttpServerRequestInfo& request, 261 const HttpServerRequestInfo& request,
277 size_t* pos) { 262 size_t* pos) {
278 WebSocket* socket = WebSocketHybi17::Create(server, connection, request, pos); 263 WebSocket* socket = WebSocketHybi17::Create(connection, request, pos);
279 if (socket) 264 if (socket)
280 return socket; 265 return socket;
281 266
282 return WebSocketHixie76::Create(server, connection, request, pos); 267 return WebSocketHixie76::Create(connection, request, pos);
283 } 268 }
284 269
285 // static 270 // static
286 WebSocket::ParseResult WebSocket::DecodeFrameHybi17( 271 WebSocket::ParseResult WebSocket::DecodeFrameHybi17(const std::string& frame,
287 const base::StringPiece& frame, 272 bool client_frame,
288 bool client_frame, 273 int* bytes_consumed,
289 int* bytes_consumed, 274 std::string* output) {
290 std::string* output) {
291 size_t data_length = frame.length(); 275 size_t data_length = frame.length();
292 if (data_length < 2) 276 if (data_length < 2)
293 return FRAME_INCOMPLETE; 277 return FRAME_INCOMPLETE;
294 278
295 const char* buffer_begin = const_cast<char*>(frame.data()); 279 const char* buffer_begin = const_cast<char*>(frame.data());
296 const char* p = buffer_begin; 280 const char* p = buffer_begin;
297 const char* buffer_end = p + data_length; 281 const char* buffer_end = p + data_length;
298 282
299 unsigned char first_byte = *p++; 283 unsigned char first_byte = *p++;
300 unsigned char second_byte = *p++; 284 unsigned char second_byte = *p++;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 if (static_cast<size_t>(buffer_end - p) < total_length) 342 if (static_cast<size_t>(buffer_end - p) < total_length)
359 return FRAME_INCOMPLETE; 343 return FRAME_INCOMPLETE;
360 344
361 if (masked) { 345 if (masked) {
362 output->resize(payload_length); 346 output->resize(payload_length);
363 const char* masking_key = p; 347 const char* masking_key = p;
364 char* payload = const_cast<char*>(p + kMaskingKeyWidthInBytes); 348 char* payload = const_cast<char*>(p + kMaskingKeyWidthInBytes);
365 for (size_t i = 0; i < payload_length; ++i) // Unmask the payload. 349 for (size_t i = 0; i < payload_length; ++i) // Unmask the payload.
366 (*output)[i] = payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes]; 350 (*output)[i] = payload[i] ^ masking_key[i % kMaskingKeyWidthInBytes];
367 } else { 351 } else {
368 output->assign(p, p + payload_length); 352 std::string buffer(p, p + payload_length);
353 output->swap(buffer);
369 } 354 }
370 355
371 size_t pos = p + actual_masking_key_length + payload_length - buffer_begin; 356 size_t pos = p + actual_masking_key_length + payload_length - buffer_begin;
372 *bytes_consumed = pos; 357 *bytes_consumed = pos;
373 return closed ? FRAME_CLOSE : FRAME_OK; 358 return closed ? FRAME_CLOSE : FRAME_OK;
374 } 359 }
375 360
376 // static 361 // static
377 std::string WebSocket::EncodeFrameHybi17(const std::string& message, 362 std::string WebSocket::EncodeFrameHybi17(const std::string& message,
378 int masking_key) { 363 int masking_key) {
(...skipping 29 matching lines...) Expand all
408 const char* mask_bytes = reinterpret_cast<char*>(&masking_key); 393 const char* mask_bytes = reinterpret_cast<char*>(&masking_key);
409 frame.insert(frame.end(), mask_bytes, mask_bytes + 4); 394 frame.insert(frame.end(), mask_bytes, mask_bytes + 4);
410 for (size_t i = 0; i < data_length; ++i) // Mask the payload. 395 for (size_t i = 0; i < data_length; ++i) // Mask the payload.
411 frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); 396 frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]);
412 } else { 397 } else {
413 frame.insert(frame.end(), data, data + data_length); 398 frame.insert(frame.end(), data, data + data_length);
414 } 399 }
415 return std::string(&frame[0], frame.size()); 400 return std::string(&frame[0], frame.size());
416 } 401 }
417 402
418 WebSocket::WebSocket(HttpServer* server, HttpConnection* connection) 403 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) {
419 : server_(server),
420 connection_(connection) {
421 } 404 }
422 405
423 } // namespace net 406 } // namespace net
OLDNEW
« no previous file with comments | « net/server/web_socket.h ('k') | net/socket/server_socket.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698