Chromium Code Reviews| 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/websockets/websocket_frame.h" | 5 #include "net/websockets/websocket_frame.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/rand_util.h" | 9 #include "base/rand_util.h" |
| 10 #include "net/base/big_endian.h" | 10 #include "net/base/big_endian.h" |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeClose = 0x8; | 35 const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodeClose = 0x8; |
| 36 const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodePing = 0x9; | 36 const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodePing = 0x9; |
| 37 const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodePong = 0xA; | 37 const WebSocketFrameHeader::OpCode WebSocketFrameHeader::kOpCodePong = 0xA; |
| 38 | 38 |
| 39 WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) { | 39 WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) { |
| 40 } | 40 } |
| 41 | 41 |
| 42 WebSocketFrameChunk::~WebSocketFrameChunk() { | 42 WebSocketFrameChunk::~WebSocketFrameChunk() { |
| 43 } | 43 } |
| 44 | 44 |
| 45 int GetWebSocketFrameHeaderSize(const WebSocketFrameHeader& header) { | |
| 46 int extended_length_size = 0; | |
| 47 if (header.payload_length > kMaxPayloadLengthWithoutExtendedLengthField && | |
| 48 header.payload_length <= kuint16max) { | |
| 49 extended_length_size = 2; | |
| 50 } else if (header.payload_length > kuint16max) { | |
| 51 extended_length_size = 8; | |
| 52 } | |
| 53 | |
| 54 int header_size = | |
|
mmenke
2012/08/20 16:33:46
optional: May want to just return this, rather th
Yuta Kitamura
2012/08/21 04:22:21
Done.
| |
| 55 WebSocketFrameHeader::kBaseHeaderSize + | |
| 56 extended_length_size + | |
| 57 (header.masked ? WebSocketFrameHeader::kMaskingKeyLength : 0); | |
| 58 return header_size; | |
| 59 } | |
| 60 | |
| 45 int WriteWebSocketFrameHeader(const WebSocketFrameHeader& header, | 61 int WriteWebSocketFrameHeader(const WebSocketFrameHeader& header, |
| 46 const WebSocketMaskingKey* masking_key, | 62 const WebSocketMaskingKey* masking_key, |
| 47 char* buffer, | 63 char* buffer, |
| 48 int buffer_size) { | 64 int buffer_size) { |
| 49 DCHECK((header.opcode & kOpCodeMask) == header.opcode) | 65 DCHECK((header.opcode & kOpCodeMask) == header.opcode) |
| 50 << "header.opcode must fit to kOpCodeMask."; | 66 << "header.opcode must fit to kOpCodeMask."; |
| 51 DCHECK(header.payload_length <= static_cast<uint64>(kint64max)) | 67 DCHECK(header.payload_length <= static_cast<uint64>(kint64max)) |
| 52 << "WebSocket specification doesn't allow a frame longer than " | 68 << "WebSocket specification doesn't allow a frame longer than " |
| 53 << "kint64max (0x7FFFFFFFFFFFFFFF) bytes."; | 69 << "kint64max (0x7FFFFFFFFFFFFFFF) bytes."; |
| 54 DCHECK_GE(buffer_size, 0); | 70 DCHECK_GE(buffer_size, 0); |
| 55 | 71 |
| 56 // WebSocket frame format is as follows: | 72 // WebSocket frame format is as follows: |
| 57 // - Common header (2 bytes) | 73 // - Common header (2 bytes) |
| 58 // - Optional extended payload length | 74 // - Optional extended payload length |
| 59 // (2 or 8 bytes, present if actual payload length is more than 125 bytes) | 75 // (2 or 8 bytes, present if actual payload length is more than 125 bytes) |
| 60 // - Optional masking key (4 bytes, present if MASK bit is on) | 76 // - Optional masking key (4 bytes, present if MASK bit is on) |
| 61 // - Actual payload (XOR masked with masking key if MASK bit is on) | 77 // - Actual payload (XOR masked with masking key if MASK bit is on) |
| 62 // | 78 // |
| 63 // This function constructs frame header (the first three in the list | 79 // This function constructs frame header (the first three in the list |
| 64 // above). | 80 // above). |
| 65 | 81 |
| 66 size_t extended_length_size = 0; | 82 int header_size = GetWebSocketFrameHeaderSize(header); |
| 67 if (header.payload_length > kMaxPayloadLengthWithoutExtendedLengthField && | |
| 68 header.payload_length <= kuint16max) { | |
| 69 extended_length_size = 2; | |
| 70 } else if (header.payload_length > kuint16max) { | |
| 71 extended_length_size = 8; | |
| 72 } | |
| 73 int header_size = | |
| 74 WebSocketFrameHeader::kBaseHeaderSize + | |
| 75 extended_length_size + | |
| 76 (header.masked ? WebSocketFrameHeader::kMaskingKeyLength : 0); | |
| 77 if (header_size > buffer_size) | 83 if (header_size > buffer_size) |
| 78 return ERR_INVALID_ARGUMENT; | 84 return ERR_INVALID_ARGUMENT; |
| 79 | 85 |
| 80 int buffer_index = 0; | 86 int buffer_index = 0; |
| 81 | 87 |
| 82 uint8 first_byte = 0u; | 88 uint8 first_byte = 0u; |
| 83 first_byte |= header.final ? kFinalBit : 0u; | 89 first_byte |= header.final ? kFinalBit : 0u; |
| 84 first_byte |= header.reserved1 ? kReserved1Bit : 0u; | 90 first_byte |= header.reserved1 ? kReserved1Bit : 0u; |
| 85 first_byte |= header.reserved2 ? kReserved2Bit : 0u; | 91 first_byte |= header.reserved2 ? kReserved2Bit : 0u; |
| 86 first_byte |= header.reserved3 ? kReserved3Bit : 0u; | 92 first_byte |= header.reserved3 ? kReserved3Bit : 0u; |
| 87 first_byte |= header.opcode & kOpCodeMask; | 93 first_byte |= header.opcode & kOpCodeMask; |
| 88 buffer[buffer_index++] = first_byte; | 94 buffer[buffer_index++] = first_byte; |
| 89 | 95 |
| 96 int extended_length_size = 0; | |
| 90 uint8 second_byte = 0u; | 97 uint8 second_byte = 0u; |
| 91 second_byte |= header.masked ? kMaskBit : 0u; | 98 second_byte |= header.masked ? kMaskBit : 0u; |
| 92 if (header.payload_length <= | 99 if (header.payload_length <= |
| 93 kMaxPayloadLengthWithoutExtendedLengthField) { | 100 kMaxPayloadLengthWithoutExtendedLengthField) { |
| 94 second_byte |= header.payload_length; | 101 second_byte |= header.payload_length; |
| 95 } else if (header.payload_length <= kuint16max) { | 102 } else if (header.payload_length <= kuint16max) { |
| 96 second_byte |= kPayloadLengthWithTwoByteExtendedLengthField; | 103 second_byte |= kPayloadLengthWithTwoByteExtendedLengthField; |
| 104 extended_length_size = 2; | |
| 97 } else { | 105 } else { |
| 98 second_byte |= kPayloadLengthWithEightByteExtendedLengthField; | 106 second_byte |= kPayloadLengthWithEightByteExtendedLengthField; |
| 107 extended_length_size = 8; | |
| 99 } | 108 } |
| 100 buffer[buffer_index++] = second_byte; | 109 buffer[buffer_index++] = second_byte; |
| 101 | 110 |
| 102 // Writes "extended payload length" field. | 111 // Writes "extended payload length" field. |
| 103 if (extended_length_size == 2u) { | 112 if (extended_length_size == 2) { |
| 104 uint16 payload_length_16 = static_cast<uint16>(header.payload_length); | 113 uint16 payload_length_16 = static_cast<uint16>(header.payload_length); |
| 105 WriteBigEndian(buffer + buffer_index, payload_length_16); | 114 WriteBigEndian(buffer + buffer_index, payload_length_16); |
| 106 buffer_index += sizeof(uint16); | 115 buffer_index += sizeof(uint16); |
| 107 } else if (extended_length_size == 8u) { | 116 } else if (extended_length_size == 8) { |
| 108 WriteBigEndian(buffer + buffer_index, header.payload_length); | 117 WriteBigEndian(buffer + buffer_index, header.payload_length); |
| 109 buffer_index += sizeof(uint64); | 118 buffer_index += sizeof(uint64); |
| 110 } | 119 } |
| 111 | 120 |
| 112 // Writes "masking key" field, if needed. | 121 // Writes "masking key" field, if needed. |
| 113 if (header.masked) { | 122 if (header.masked) { |
| 114 DCHECK(masking_key); | 123 DCHECK(masking_key); |
| 115 std::copy(masking_key->key, | 124 std::copy(masking_key->key, |
| 116 masking_key->key + WebSocketFrameHeader::kMaskingKeyLength, | 125 masking_key->key + WebSocketFrameHeader::kMaskingKeyLength, |
| 117 buffer + buffer_index); | 126 buffer + buffer_index); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 146 // (4 or 8 bytes), instead of XOR'ing every byte. | 155 // (4 or 8 bytes), instead of XOR'ing every byte. |
| 147 size_t masking_key_offset = frame_offset % kMaskingKeyLength; | 156 size_t masking_key_offset = frame_offset % kMaskingKeyLength; |
| 148 for (int i = 0; i < data_size; ++i) { | 157 for (int i = 0; i < data_size; ++i) { |
| 149 data[i] ^= masking_key.key[masking_key_offset++]; | 158 data[i] ^= masking_key.key[masking_key_offset++]; |
| 150 if (masking_key_offset == kMaskingKeyLength) | 159 if (masking_key_offset == kMaskingKeyLength) |
| 151 masking_key_offset = 0; | 160 masking_key_offset = 0; |
| 152 } | 161 } |
| 153 } | 162 } |
| 154 | 163 |
| 155 } // namespace net | 164 } // namespace net |
| OLD | NEW |