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 <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" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 connection_->Send(&message_start, 1); | 104 connection_->Send(&message_start, 1); |
105 connection_->Send(message); | 105 connection_->Send(message); |
106 connection_->Send(&message_end, 1); | 106 connection_->Send(&message_end, 1); |
107 } | 107 } |
108 | 108 |
109 private: | 109 private: |
110 static const int kWebSocketHandshakeBodyLen; | 110 static const int kWebSocketHandshakeBodyLen; |
111 | 111 |
112 WebSocketHixie76(HttpConnection* connection, | 112 WebSocketHixie76(HttpConnection* connection, |
113 const HttpServerRequestInfo& request, | 113 const HttpServerRequestInfo& request, |
114 size_t* pos) : WebSocket(connection) { | 114 size_t* pos) |
| 115 : WebSocket(connection) { |
115 std::string key1 = request.GetHeaderValue("sec-websocket-key1"); | 116 std::string key1 = request.GetHeaderValue("sec-websocket-key1"); |
116 std::string key2 = request.GetHeaderValue("sec-websocket-key2"); | 117 std::string key2 = request.GetHeaderValue("sec-websocket-key2"); |
117 | 118 |
118 if (key1.empty()) { | 119 if (key1.empty()) { |
119 connection->Send(HttpServerResponseInfo::CreateFor500( | 120 connection->Send(HttpServerResponseInfo::CreateFor500( |
120 "Invalid request format. Sec-WebSocket-Key1 is empty or isn't " | 121 "Invalid request format. Sec-WebSocket-Key1 is empty or isn't " |
121 "specified.")); | 122 "specified.")); |
122 return; | 123 return; |
123 } | 124 } |
124 | 125 |
125 if (key2.empty()) { | 126 if (key2.empty()) { |
126 connection->Send(HttpServerResponseInfo::CreateFor500( | 127 connection->Send(HttpServerResponseInfo::CreateFor500( |
127 "Invalid request format. Sec-WebSocket-Key2 is empty or isn't " | 128 "Invalid request format. Sec-WebSocket-Key2 is empty or isn't " |
128 "specified.")); | 129 "specified.")); |
129 return; | 130 return; |
130 } | 131 } |
131 | 132 |
132 key3_ = connection->recv_data().substr( | 133 key3_ = |
133 *pos, | 134 connection->recv_data().substr(*pos, *pos + kWebSocketHandshakeBodyLen); |
134 *pos + kWebSocketHandshakeBodyLen); | |
135 *pos += kWebSocketHandshakeBodyLen; | 135 *pos += kWebSocketHandshakeBodyLen; |
136 } | 136 } |
137 | 137 |
138 std::string key3_; | 138 std::string key3_; |
139 | 139 |
140 DISALLOW_COPY_AND_ASSIGN(WebSocketHixie76); | 140 DISALLOW_COPY_AND_ASSIGN(WebSocketHixie76); |
141 }; | 141 }; |
142 | 142 |
143 const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8; | 143 const int WebSocketHixie76::kWebSocketHandshakeBodyLen = 8; |
144 | 144 |
145 | |
146 // Constants for hybi-10 frame format. | 145 // Constants for hybi-10 frame format. |
147 | 146 |
148 typedef int OpCode; | 147 typedef int OpCode; |
149 | 148 |
150 const OpCode kOpCodeContinuation = 0x0; | 149 const OpCode kOpCodeContinuation = 0x0; |
151 const OpCode kOpCodeText = 0x1; | 150 const OpCode kOpCodeText = 0x1; |
152 const OpCode kOpCodeBinary = 0x2; | 151 const OpCode kOpCodeBinary = 0x2; |
153 const OpCode kOpCodeClose = 0x8; | 152 const OpCode kOpCodeClose = 0x8; |
154 const OpCode kOpCodePing = 0x9; | 153 const OpCode kOpCodePing = 0x9; |
155 const OpCode kOpCodePong = 0xA; | 154 const OpCode kOpCodePong = 0xA; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 if (closed_) | 220 if (closed_) |
222 return; | 221 return; |
223 std::string data = WebSocket::EncodeFrameHybi17(message, 0); | 222 std::string data = WebSocket::EncodeFrameHybi17(message, 0); |
224 connection_->Send(data); | 223 connection_->Send(data); |
225 } | 224 } |
226 | 225 |
227 private: | 226 private: |
228 WebSocketHybi17(HttpConnection* connection, | 227 WebSocketHybi17(HttpConnection* connection, |
229 const HttpServerRequestInfo& request, | 228 const HttpServerRequestInfo& request, |
230 size_t* pos) | 229 size_t* pos) |
231 : WebSocket(connection), | 230 : WebSocket(connection), |
232 op_code_(0), | 231 op_code_(0), |
233 final_(false), | 232 final_(false), |
234 reserved1_(false), | 233 reserved1_(false), |
235 reserved2_(false), | 234 reserved2_(false), |
236 reserved3_(false), | 235 reserved3_(false), |
237 masked_(false), | 236 masked_(false), |
238 payload_(0), | 237 payload_(0), |
239 payload_length_(0), | 238 payload_length_(0), |
240 frame_end_(0), | 239 frame_end_(0), |
241 closed_(false) { | 240 closed_(false) {} |
242 } | |
243 | 241 |
244 OpCode op_code_; | 242 OpCode op_code_; |
245 bool final_; | 243 bool final_; |
246 bool reserved1_; | 244 bool reserved1_; |
247 bool reserved2_; | 245 bool reserved2_; |
248 bool reserved3_; | 246 bool reserved3_; |
249 bool masked_; | 247 bool masked_; |
250 const char* payload_; | 248 const char* payload_; |
251 size_t payload_length_; | 249 size_t payload_length_; |
252 const char* frame_end_; | 250 const char* frame_end_; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 bool reserved1 = (first_byte & kReserved1Bit) != 0; | 285 bool reserved1 = (first_byte & kReserved1Bit) != 0; |
288 bool reserved2 = (first_byte & kReserved2Bit) != 0; | 286 bool reserved2 = (first_byte & kReserved2Bit) != 0; |
289 bool reserved3 = (first_byte & kReserved3Bit) != 0; | 287 bool reserved3 = (first_byte & kReserved3Bit) != 0; |
290 int op_code = first_byte & kOpCodeMask; | 288 int op_code = first_byte & kOpCodeMask; |
291 bool masked = (second_byte & kMaskBit) != 0; | 289 bool masked = (second_byte & kMaskBit) != 0; |
292 if (!final || reserved1 || reserved2 || reserved3) | 290 if (!final || reserved1 || reserved2 || reserved3) |
293 return FRAME_ERROR; // Extensions and not supported. | 291 return FRAME_ERROR; // Extensions and not supported. |
294 | 292 |
295 bool closed = false; | 293 bool closed = false; |
296 switch (op_code) { | 294 switch (op_code) { |
297 case kOpCodeClose: | 295 case kOpCodeClose: |
298 closed = true; | 296 closed = true; |
299 break; | 297 break; |
300 case kOpCodeText: | 298 case kOpCodeText: |
301 break; | 299 break; |
302 case kOpCodeBinary: // We don't support binary frames yet. | 300 case kOpCodeBinary: // We don't support binary frames yet. |
303 case kOpCodeContinuation: // We don't support binary frames yet. | 301 case kOpCodeContinuation: // We don't support binary frames yet. |
304 case kOpCodePing: // We don't support binary frames yet. | 302 case kOpCodePing: // We don't support binary frames yet. |
305 case kOpCodePong: // We don't support binary frames yet. | 303 case kOpCodePong: // We don't support binary frames yet. |
306 default: | 304 default: |
307 return FRAME_ERROR; | 305 return FRAME_ERROR; |
308 } | 306 } |
309 | 307 |
310 if (client_frame && !masked) // In Hybi-17 spec client MUST mask his frame. | 308 if (client_frame && !masked) // In Hybi-17 spec client MUST mask his frame. |
311 return FRAME_ERROR; | 309 return FRAME_ERROR; |
312 | 310 |
313 uint64 payload_length64 = second_byte & kPayloadLengthMask; | 311 uint64 payload_length64 = second_byte & kPayloadLengthMask; |
314 if (payload_length64 > kMaxSingleBytePayloadLength) { | 312 if (payload_length64 > kMaxSingleBytePayloadLength) { |
315 int extended_payload_length_size; | 313 int extended_payload_length_size; |
316 if (payload_length64 == kTwoBytePayloadLengthField) | 314 if (payload_length64 == kTwoBytePayloadLengthField) |
317 extended_payload_length_size = 2; | 315 extended_payload_length_size = 2; |
318 else { | 316 else { |
319 DCHECK(payload_length64 == kEightBytePayloadLengthField); | 317 DCHECK(payload_length64 == kEightBytePayloadLengthField); |
320 extended_payload_length_size = 8; | 318 extended_payload_length_size = 8; |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 frame.push_back(data_length & 0xFF); | 373 frame.push_back(data_length & 0xFF); |
376 } else { | 374 } else { |
377 frame.push_back(kEightBytePayloadLengthField | mask_key_bit); | 375 frame.push_back(kEightBytePayloadLengthField | mask_key_bit); |
378 char extended_payload_length[8]; | 376 char extended_payload_length[8]; |
379 size_t remaining = data_length; | 377 size_t remaining = data_length; |
380 // Fill the length into extended_payload_length in the network byte order. | 378 // Fill the length into extended_payload_length in the network byte order. |
381 for (int i = 0; i < 8; ++i) { | 379 for (int i = 0; i < 8; ++i) { |
382 extended_payload_length[7 - i] = remaining & 0xFF; | 380 extended_payload_length[7 - i] = remaining & 0xFF; |
383 remaining >>= 8; | 381 remaining >>= 8; |
384 } | 382 } |
385 frame.insert(frame.end(), | 383 frame.insert( |
386 extended_payload_length, | 384 frame.end(), extended_payload_length, extended_payload_length + 8); |
387 extended_payload_length + 8); | |
388 DCHECK(!remaining); | 385 DCHECK(!remaining); |
389 } | 386 } |
390 | 387 |
391 const char* data = const_cast<char*>(message.data()); | 388 const char* data = const_cast<char*>(message.data()); |
392 if (masking_key != 0) { | 389 if (masking_key != 0) { |
393 const char* mask_bytes = reinterpret_cast<char*>(&masking_key); | 390 const char* mask_bytes = reinterpret_cast<char*>(&masking_key); |
394 frame.insert(frame.end(), mask_bytes, mask_bytes + 4); | 391 frame.insert(frame.end(), mask_bytes, mask_bytes + 4); |
395 for (size_t i = 0; i < data_length; ++i) // Mask the payload. | 392 for (size_t i = 0; i < data_length; ++i) // Mask the payload. |
396 frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); | 393 frame.push_back(data[i] ^ mask_bytes[i % kMaskingKeyWidthInBytes]); |
397 } else { | 394 } else { |
398 frame.insert(frame.end(), data, data + data_length); | 395 frame.insert(frame.end(), data, data + data_length); |
399 } | 396 } |
400 return std::string(&frame[0], frame.size()); | 397 return std::string(&frame[0], frame.size()); |
401 } | 398 } |
402 | 399 |
403 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) { | 400 WebSocket::WebSocket(HttpConnection* connection) : connection_(connection) { |
404 } | 401 } |
405 | 402 |
406 } // namespace net | 403 } // namespace net |
OLD | NEW |