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 |