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