Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: net/websockets/websocket_frame.cc

Issue 10825444: Add a function that calculates the size of WebSocket frame header. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Matt's comment. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/websockets/websocket_frame.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « net/websockets/websocket_frame.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698