| 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 |