Index: net/websockets/websocket_frame.cc |
diff --git a/net/websockets/websocket_frame.cc b/net/websockets/websocket_frame.cc |
deleted file mode 100644 |
index a90cc0a1c304b7dae70fb5d87b990beebe18c30e..0000000000000000000000000000000000000000 |
--- a/net/websockets/websocket_frame.cc |
+++ /dev/null |
@@ -1,239 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "net/websockets/websocket_frame.h" |
- |
-#include <algorithm> |
- |
-#include "base/basictypes.h" |
-#include "base/big_endian.h" |
-#include "base/logging.h" |
-#include "base/rand_util.h" |
-#include "net/base/io_buffer.h" |
-#include "net/base/net_errors.h" |
- |
-namespace { |
- |
-const uint8 kFinalBit = 0x80; |
-const uint8 kReserved1Bit = 0x40; |
-const uint8 kReserved2Bit = 0x20; |
-const uint8 kReserved3Bit = 0x10; |
-const uint8 kOpCodeMask = 0xF; |
-const uint8 kMaskBit = 0x80; |
-const uint64 kMaxPayloadLengthWithoutExtendedLengthField = 125; |
-const uint64 kPayloadLengthWithTwoByteExtendedLengthField = 126; |
-const uint64 kPayloadLengthWithEightByteExtendedLengthField = 127; |
- |
-inline void MaskWebSocketFramePayloadByBytes( |
- const net::WebSocketMaskingKey& masking_key, |
- size_t masking_key_offset, |
- char* const begin, |
- char* const end) { |
- for (char* masked = begin; masked != end; ++masked) { |
- *masked ^= masking_key.key[masking_key_offset++]; |
- if (masking_key_offset == net::WebSocketFrameHeader::kMaskingKeyLength) |
- masking_key_offset = 0; |
- } |
-} |
- |
-} // Unnamed namespace. |
- |
-namespace net { |
- |
-scoped_ptr<WebSocketFrameHeader> WebSocketFrameHeader::Clone() const { |
- scoped_ptr<WebSocketFrameHeader> ret(new WebSocketFrameHeader(opcode)); |
- ret->CopyFrom(*this); |
- return ret.Pass(); |
-} |
- |
-void WebSocketFrameHeader::CopyFrom(const WebSocketFrameHeader& source) { |
- final = source.final; |
- reserved1 = source.reserved1; |
- reserved2 = source.reserved2; |
- reserved3 = source.reserved3; |
- opcode = source.opcode; |
- masked = source.masked; |
- payload_length = source.payload_length; |
-} |
- |
-WebSocketFrame::WebSocketFrame(WebSocketFrameHeader::OpCode opcode) |
- : header(opcode) {} |
- |
-WebSocketFrame::~WebSocketFrame() {} |
- |
-WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) {} |
- |
-WebSocketFrameChunk::~WebSocketFrameChunk() {} |
- |
-int GetWebSocketFrameHeaderSize(const WebSocketFrameHeader& header) { |
- int extended_length_size = 0; |
- if (header.payload_length > kMaxPayloadLengthWithoutExtendedLengthField && |
- header.payload_length <= kuint16max) { |
- extended_length_size = 2; |
- } else if (header.payload_length > kuint16max) { |
- extended_length_size = 8; |
- } |
- |
- return (WebSocketFrameHeader::kBaseHeaderSize + extended_length_size + |
- (header.masked ? WebSocketFrameHeader::kMaskingKeyLength : 0)); |
-} |
- |
-int WriteWebSocketFrameHeader(const WebSocketFrameHeader& header, |
- const WebSocketMaskingKey* masking_key, |
- char* buffer, |
- int buffer_size) { |
- DCHECK((header.opcode & kOpCodeMask) == header.opcode) |
- << "header.opcode must fit to kOpCodeMask."; |
- DCHECK(header.payload_length <= static_cast<uint64>(kint64max)) |
- << "WebSocket specification doesn't allow a frame longer than " |
- << "kint64max (0x7FFFFFFFFFFFFFFF) bytes."; |
- DCHECK_GE(buffer_size, 0); |
- |
- // WebSocket frame format is as follows: |
- // - Common header (2 bytes) |
- // - Optional extended payload length |
- // (2 or 8 bytes, present if actual payload length is more than 125 bytes) |
- // - Optional masking key (4 bytes, present if MASK bit is on) |
- // - Actual payload (XOR masked with masking key if MASK bit is on) |
- // |
- // This function constructs frame header (the first three in the list |
- // above). |
- |
- int header_size = GetWebSocketFrameHeaderSize(header); |
- if (header_size > buffer_size) |
- return ERR_INVALID_ARGUMENT; |
- |
- int buffer_index = 0; |
- |
- uint8 first_byte = 0u; |
- first_byte |= header.final ? kFinalBit : 0u; |
- first_byte |= header.reserved1 ? kReserved1Bit : 0u; |
- first_byte |= header.reserved2 ? kReserved2Bit : 0u; |
- first_byte |= header.reserved3 ? kReserved3Bit : 0u; |
- first_byte |= header.opcode & kOpCodeMask; |
- buffer[buffer_index++] = first_byte; |
- |
- int extended_length_size = 0; |
- uint8 second_byte = 0u; |
- second_byte |= header.masked ? kMaskBit : 0u; |
- if (header.payload_length <= kMaxPayloadLengthWithoutExtendedLengthField) { |
- second_byte |= header.payload_length; |
- } else if (header.payload_length <= kuint16max) { |
- second_byte |= kPayloadLengthWithTwoByteExtendedLengthField; |
- extended_length_size = 2; |
- } else { |
- second_byte |= kPayloadLengthWithEightByteExtendedLengthField; |
- extended_length_size = 8; |
- } |
- buffer[buffer_index++] = second_byte; |
- |
- // Writes "extended payload length" field. |
- if (extended_length_size == 2) { |
- uint16 payload_length_16 = static_cast<uint16>(header.payload_length); |
- base::WriteBigEndian(buffer + buffer_index, payload_length_16); |
- buffer_index += sizeof(payload_length_16); |
- } else if (extended_length_size == 8) { |
- base::WriteBigEndian(buffer + buffer_index, header.payload_length); |
- buffer_index += sizeof(header.payload_length); |
- } |
- |
- // Writes "masking key" field, if needed. |
- if (header.masked) { |
- DCHECK(masking_key); |
- std::copy(masking_key->key, |
- masking_key->key + WebSocketFrameHeader::kMaskingKeyLength, |
- buffer + buffer_index); |
- buffer_index += WebSocketFrameHeader::kMaskingKeyLength; |
- } else { |
- DCHECK(!masking_key); |
- } |
- |
- DCHECK_EQ(header_size, buffer_index); |
- return header_size; |
-} |
- |
-WebSocketMaskingKey GenerateWebSocketMaskingKey() { |
- // Masking keys should be generated from a cryptographically secure random |
- // number generator, which means web application authors should not be able |
- // to guess the next value of masking key. |
- WebSocketMaskingKey masking_key; |
- base::RandBytes(masking_key.key, WebSocketFrameHeader::kMaskingKeyLength); |
- return masking_key; |
-} |
- |
-void MaskWebSocketFramePayload(const WebSocketMaskingKey& masking_key, |
- uint64 frame_offset, |
- char* const data, |
- int data_size) { |
- static const size_t kMaskingKeyLength = |
- WebSocketFrameHeader::kMaskingKeyLength; |
- |
- DCHECK_GE(data_size, 0); |
- |
- // Most of the masking is done one word at a time, except for the beginning |
- // and the end of the buffer which may be unaligned. We use size_t to get the |
- // word size for this architecture. We require it be a multiple of |
- // kMaskingKeyLength in size. |
- typedef size_t PackedMaskType; |
- PackedMaskType packed_mask_key = 0; |
- static const size_t kPackedMaskKeySize = sizeof(packed_mask_key); |
- static_assert((kPackedMaskKeySize >= kMaskingKeyLength && |
- kPackedMaskKeySize % kMaskingKeyLength == 0), |
- "word size is not a multiple of mask length"); |
- char* const end = data + data_size; |
- // If the buffer is too small for the vectorised version to be useful, revert |
- // to the byte-at-a-time implementation early. |
- if (data_size <= static_cast<int>(kPackedMaskKeySize * 2)) { |
- MaskWebSocketFramePayloadByBytes( |
- masking_key, frame_offset % kMaskingKeyLength, data, end); |
- return; |
- } |
- const size_t data_modulus = |
- reinterpret_cast<size_t>(data) % kPackedMaskKeySize; |
- char* const aligned_begin = |
- data_modulus == 0 ? data : (data + kPackedMaskKeySize - data_modulus); |
- // Guaranteed by the above check for small data_size. |
- DCHECK(aligned_begin < end); |
- MaskWebSocketFramePayloadByBytes( |
- masking_key, frame_offset % kMaskingKeyLength, data, aligned_begin); |
- const size_t end_modulus = reinterpret_cast<size_t>(end) % kPackedMaskKeySize; |
- char* const aligned_end = end - end_modulus; |
- // Guaranteed by the above check for small data_size. |
- DCHECK(aligned_end > aligned_begin); |
- // Create a version of the mask which is rotated by the appropriate offset |
- // for our alignment. The "trick" here is that 0 XORed with the mask will |
- // give the value of the mask for the appropriate byte. |
- char realigned_mask[kMaskingKeyLength] = {}; |
- MaskWebSocketFramePayloadByBytes( |
- masking_key, |
- (frame_offset + aligned_begin - data) % kMaskingKeyLength, |
- realigned_mask, |
- realigned_mask + kMaskingKeyLength); |
- |
- for (size_t i = 0; i < kPackedMaskKeySize; i += kMaskingKeyLength) { |
- // memcpy() is allegedly blessed by the C++ standard for type-punning. |
- memcpy(reinterpret_cast<char*>(&packed_mask_key) + i, |
- realigned_mask, |
- kMaskingKeyLength); |
- } |
- |
- // The main loop. |
- for (char* merged = aligned_begin; merged != aligned_end; |
- merged += kPackedMaskKeySize) { |
- // This is not quite standard-compliant C++. However, the standard-compliant |
- // equivalent (using memcpy()) compiles to slower code using g++. In |
- // practice, this will work for the compilers and architectures currently |
- // supported by Chromium, and the tests are extremely unlikely to pass if a |
- // future compiler/architecture breaks it. |
- *reinterpret_cast<PackedMaskType*>(merged) ^= packed_mask_key; |
- } |
- |
- MaskWebSocketFramePayloadByBytes( |
- masking_key, |
- (frame_offset + (aligned_end - data)) % kMaskingKeyLength, |
- aligned_end, |
- end); |
-} |
- |
-} // namespace net |